Compare commits

..

142 Commits

Author SHA1 Message Date
Martin Hořeňovský
216713a406 v2.13.8 2022-01-03 21:21:39 +01:00
Bernhard Manfred Gruber
e9e4117016 Remove double-underscores in macros
Such identifiers are reserved by the C++ standard.
Fixes part of #578.
2021-12-16 14:34:04 +01:00
Dan Raviv
8a06a6dce8 Fix typo 2021-12-10 16:01:55 +01:00
Xo Wang
33794a204c Fix clang analyzer warning about FilterGenerator
Refactor FilterGenerator to remove ctor call to overridden method next()
in order to address clang static analyzer diagnostic:

catch2-src/single_include/catch2/catch.hpp:4166:42: note: Call to virtual method 'FilterGenerator::next' during construction bypasses virtual dispatch
                auto has_initial_value = next();
                                         ^~~~~~
2021-11-24 11:30:03 +01:00
Martin Hořeňovský
f45dac8fc1 Add broken test 2021-11-24 11:30:03 +01:00
Martin Hořeňovský
f2f0dcc511 Add VS2015 + char literals in GENERATE issue to known-limitations
Closes #2207
2021-11-15 23:27:17 +01:00
Alecto Irene Perez
dba29b60d6 Fixed #2272: Compilation failure with C++20 (#2297)
* Suppressed warning for comma-in-indexing-operator in tests that check
  that specific behaviour.
* Made deprecated (and removed) allocator usings conditional on the tests
  being compiled with old version of MSVC that still requires them.

Fixes #2272
2021-10-04 21:11:03 +02:00
Rupert Nash
3d01f3ae32 Backport changes from 7bea1e2ac36ac54b648ae5c9d381a59bc69db912 to fix #2273 for 2.x 2021-09-18 21:24:03 +02:00
Biswapriyo Nath
85c9544fa4 pkgconfig: Add missing entries
This adds prefix, exec_prefix and libdir fields
2021-09-10 20:08:03 +02:00
Jørgen P. Tjernø
4b9780201b Fix warning suppressions leaking under clang.exe
When running clang.exe under Windows, catch.hpp leaks warning
suppressions because it uses `#pragma warning(push)` & `#pragma
warning(pop)` around warning suppressions like `#pragma clang diagnostic
ignore "-Wunused-variable"`, instead of using `#pragma clang diagnostic
push` and `#pragma clang diagnostic pop`.

This fixes that by only defining
`CATCH_INTERNAL_START_WARNINGS_SUPPRESSION` and
`CATCH_INTERNAL_STOP_WARNINGS_SUPPRESSION` to be the cl.exe variants if
`defined(_MSC_VER) && !defined(__clang__)`.
2021-08-30 23:26:51 +02:00
Martin Hořeňovský
c4e3767e26 v2.13.7 2021-07-28 20:30:51 +02:00
Martin Hořeňovský
eea3e9a5b5 Mark !mayfail tests as skipped in the JUnit reporter
Should fix #2116
2021-07-27 23:16:01 +02:00
Martin Hořeňovský
7727c15290 Remove Conan builds from travis-CI 2021-06-07 20:02:30 +02:00
Dimitrij Mijoski
531a149ae7 Fix compiling v2.x with C++17 + Clang 5 + libstdc++ v5
This basically tests the combination where the compiler supports most
of C++17 but the library does not.
2021-05-25 23:50:45 +02:00
Martin Hořeňovský
9683570be7 Tiny optimization in JUnit reporter 2021-05-23 11:31:33 +02:00
Martin Hořeňovský
581c46249a JUnit reporter uses only 3 decimal places when reporting durations
We used to use whatever precision we ended up having from C++'s
stdlib. However, some relatively popular tools, like Jenkins,
use Maven SureFire XML schema to validate JUnit test reports, and
Maven SureFire schema requires the duration to have at most 3
decimal places.

For compatibility, the JUnit reporter will now respect this
limitation.

Closes #2221
2021-05-22 23:45:43 +02:00
Evgeny Proydakov
b15b862d86 Fixed noexcept benchmark build for gcc. 2021-05-21 20:49:16 +02:00
Martin Hořeňovský
6971476563 Ensure that <iterator> is included before back_inserter is used
Closes #2231
2021-05-21 20:20:00 +02:00
Martin Hořeňovský
5c88067bd3 v2.13.6 2021-04-16 20:14:58 +02:00
Georg Schwab
86a4d704bc fixed inconsistent semicolon expansion in catch_discover_tests (Bug #2214) 2021-04-16 17:26:08 +02:00
Matteo Beniamino
469a717395 Fixed [dis]engage_platform declarations mismatch 2021-04-13 19:50:32 +02:00
Martin Hořeňovský
42e368dd0a v2.13.5 2021-04-10 23:48:32 +02:00
Clare Macrae
1ff1f2741d Prevent Catch2 v2 tests running if loaded as a sub-project
See #2202
2021-04-09 23:54:13 +02:00
Julien Brianceau
269f96e2bc Fix typos in the code base
Note that only documentation and comments are impacted by this change.
2021-04-08 18:06:36 +02:00
Martin Hořeňovský
cec35630fb Don't build Catch2WithMain target by default for v2
The `Catch2WithMain` target was added experimentally for v2.13.4
to provide potentially better compilation (and link) times to users.
However, having it compiled by default causes worse experience for
people who do not use it, and for the v2 versions the single include
distribution is still the main one.

Closes #2142
2021-04-05 18:04:31 +02:00
Martin Hořeňovský
b8b03da534 Mangle doccoments to avoid breaking single include stitching 2021-04-04 18:09:29 +02:00
Martin Hořeňovský
8f277a54c0 Significantly refactor fatal error handling
Because new glibc has changed `MINSIGSTKSZ` to be a syscall instead
of being constant, the signal posix handling needed changes, as it
used the value in constexpr context, for deciding size of an array.
It would be simple to fix it by having the handler determine the
signal handling stack size and allocate the memory every time the
handler is being installed, but that would add another allocation
and a syscall every time a test case is entered.

Instead, I split apart the idea of preparing fatal error handlers,
and engaging them, so that the memory can be allocated only once
and still be guarded by RAII.

Also turns out that Catch2's use of `MINSIGSTKSZ` was wrong, and
we should've been using `SIGSTKSZ` the whole time, which we use now.

Closes #2178
2021-04-04 18:09:26 +02:00
Pavel Kamenov
4cb3220a8a Add lcc to the list of unwanted compilers that mimic gcc 2021-04-04 14:05:39 +02:00
Scott Hutchinson
b025a007b9 Wrap all std::min and std::max calls in parentheses 2021-02-20 23:28:20 +01:00
Rob Boehne
68975e3ff3 [Issue 2154] Correct error when building with IBM's latest XLC (#2155)
* [Issue 2154] Correct error when building with IBM's latest XLC compiler with xlclang++ front-end.

On AIX, the XLC 16.1.0.1 compiler considers the call to `std::abs` ambigious, so it needs help with a static_cast to the type of the template argument.

Co-authored-by: Martin Hořeňovský <martin.horenovsky@gmail.com>
2021-01-21 22:50:49 +01:00
Martin Hořeňovský
bcb9ea8cb5 Merge pull request #2157 from tdegeus/patch
Making target detection on Mac more robust
2021-01-21 15:35:23 +01:00
Tom de Geus
d4c9494eb5 Making target detection on Mac more robust 2021-01-20 21:12:18 +01:00
Mathieu Mirmont
bed285af07 Make the build reproducible with g++-8 and clang-10
Make the build reproducible by removing references to the source
directory from the Catch2WithMain static library.
2021-01-13 18:09:24 +01:00
Martin Hořeňovský
de6fe184a9 v2.13.4 2020-12-29 15:03:40 +01:00
Martin Hořeňovský
fe3dddcc6d Fix updateVersionPlaceholder when the placeholder starts the line 2020-12-29 15:02:25 +01:00
Reinhold Gschweicher
18ab353e55 Add deprecation warning in ParseAndCatchTests
Parsing C++ with regex in CMake is error prone and regularly leads to silently
dropped (not run) test cases.

Going forward the function `catch_discover_tests` from `contrib/CMake.cmake`
should be used.

For more information see https://github.com/catchorg/Catch2/issues/2092#issuecomment-747342765
2020-12-21 13:15:36 +01:00
Reinhold Gschweicher
2375a7f5b7 Fix Catch.cmake helper by setting variable globally
Set `_CATCH_DISCOVER_TESTS_SCRIPT` helper variable globally. Otherwise in a
scoped call (like `add_subdirectory()`) the variable gets lost. This lost
variable results in a post build error with not much information to lead to the
root of the problem.

This enables the usage of the helper script with the following example structure

- CMakeLists.txt (project root with `add_subdirectory(external/catch2)`
- external/catch2
  - CMakeLists.txt (contents listed below)
  - contrib/Catch.cmake
  - contrib/CatchAddTests.cmake
  - catch2/catch.hpp
- tests
  - CMakeLists.txt (add tests with `catch_discover_tests(${PROJECT_NAME})`)

contents of project specific helper `external/catch2/CMakeLists.txt`
```cmake
cmake_minimum_required (VERSION 3.1...${CMAKE_VERSION})
project(Catch2 LANGUAGES CXX VERSION 2.13.3)
add_library(Catch2 INTERFACE)
target_include_directories(Catch2
  INTERFACE
    $<BUILD_INTERFACE:${CMAKE_CURRENT_LIST_DIR}>
)
 # provide a namespaced alias for clients to 'link' against if catch is included as a sub-project
add_library(Catch2::Catch2 ALIAS Catch2)
include(contrib/Catch.cmake)
```
2020-12-17 18:50:04 +01:00
Martin Hořeňovský
fac517d571 Fix conan package build 2020-11-26 15:05:58 +01:00
Florian Berchtold
578f8b8006 Add bazel support 2020-11-18 21:37:12 +01:00
Deniz Evrenci
92f8b01dfa Add the static library Catch2WithMain
It should provide a shared impl for all targets that need to link
against Catch2's implementation. However, due to limitations of
C++ linking and Catch2's v2 implementation, this is only experimental
and might not work under some circumstances.
2020-11-18 21:37:10 +01:00
Martin Hořeňovský
dc7e705672 Small cleanups for the reworked test case order hashing 2020-11-17 21:08:33 +01:00
Sergio Losilla
3ba745552b Modified hash to make it more independent of the choice of test names. 2020-11-17 20:58:16 +01:00
Martin Hořeňovský
ff349a50bf v2.13.3 2020-10-31 18:21:23 +01:00
Martin Hořeňovský
aca2472d40 Stop uploading new releases to wandbox 2020-10-31 18:21:00 +01:00
Martin Hořeňovský
765ac08f08 Fix potential infinite loops in generators combined with section filter
The problem was that under specific circumstances, namely that none
of their children progressed, `GeneratorTracker` will not progress.
This was changed recently, to allow for code like this, where a
`SECTION` follows a `GENERATE` at the same level:

```cpp
SECTION("A") {}
auto a = GENERATE(1, 2);
SECTION("B") {}
```

However, this interacted badly with `SECTION` filters (`-c foo`),
as they could deactivate all `SECTION`s below a generator, and thus
stop it from progressing forever. This commit makes GeneratorTracker
check whether there are any filters active, and if they are, it checks
whether its section-children can ever run.

Fixes #2025
2020-10-31 18:04:15 +01:00
Martin Hořeňovský
8dd25b0410 Fix bunch of links to master to point to v2.x branch
Fixes #2063
Related to #2050
2020-10-21 15:30:35 +02:00
Reinhold Gschweicher
69297ceeb6 Consider CMP0110 add_test() policy
CMake 3.19 introduces new add_test() behavior guarded with the policy
CMP0110.

See: https://cmake.org/cmake/help/latest/policy/CMP0110.html

Update the helper script ParseAndAddCatchTests to consider the policy and
handle the test case name accordingly.
2020-10-20 23:25:45 +02:00
Reinhold Gschweicher
2d30df3500 Fix indentation in ParseAndAddCatchTests
Consistently use 4 spaces instead of tabs
2020-10-20 13:48:46 +02:00
Reinhold Gschweicher
77b2a7daea Fix CMake regex to add tests
Fix regex that requires two string arguments in the form of
TEST_CASE("a", "b") resulting in not finding TEST_CASE("a") entries.

See https://regex101.com/r/JygOND/1

Fixes: https://github.com/catchorg/Catch2/issues/2055
2020-10-20 13:48:14 +02:00
laoshanxi
e905edb10f Add AppMesh to Open Source projects using Catch 2020-10-20 13:48:14 +02:00
Martin Hořeňovský
87074da73e v2.13.2 2020-10-07 11:43:02 +02:00
Martin Hořeňovský
e6f5e05ebc Improve detection of std::uncaught_exceptions support
The problem was that Catch2 did not reliably include `<exception>`
before it checked for the feature test macro for
`std::uncaught_exceptions`. To avoid overhead of including
`<exception>` everywhere, the configuration check was split out
into a separate header.

Closes #2021
2020-10-06 11:07:53 +02:00
Rémy Salim
44900d5371 Add WORKING_DIRECTORY to CatchAddTests.cmake commands 2020-10-02 23:29:40 +02:00
Martin Hořeňovský
7c75ecaef4 Workaround AppleClang bug by renaming TestHasher constructor argument
As far as I understand the standard, if there is a function called
`rng` in the global namespace, and a function argument called `rng`,
then the argument should shadow the function. This then means that
uses of `rng` inside the function should refer to the argument.

This is not the case for AppleClang 12.0.0. Luckily the workaround
is simple enough; just rename the argument. Given that the function
is 3 lines and uncomplicated, the change of the name doesn't really
affect readability.

Still, WTF AppleClang?

Closes #2030
2020-10-02 23:22:49 +02:00
Matt Godbolt
fba0feeba1 Add missing syntax highlighting tag 2020-09-24 22:43:07 +02:00
Ansel Sermersheim
3e8800beb1 Support template test cases in ParseAndAddCatchTests
* Change regex to allow parentheses inside the test macro for a type list
* Append a wildcard to the CTestName if the test case is a template
* Also change the regular expression so parentheses are allowed in names
  (fixes #1848)
2020-09-24 22:42:32 +02:00
Martin Hořeňovský
314a05d809 Merge pull request #2023 from globberwops/feature/add-reporter-and-output-dir
Add REPORTER and OUTPUT_DIR args to catch_discover_tests
2020-09-23 22:47:21 +02:00
Martin Stump
eadf4e32b6 Add REPORTER and OUTPUT_* args 2020-09-23 19:12:06 +02:00
Florian Berchtold
f9620d11be Docu/Show how to use CMake FetchContent (#2028) 2020-09-20 18:09:33 +02:00
Will Pazner
00db4fb497 Disable __builtin_constant_p when compiling with nvcc 2020-09-18 16:07:18 +02:00
kotaiadam
2fc83e7e9c fixes bug in example - undeclared identifier
j was not declared in `SECTION("two")`
2020-09-12 11:40:30 +02:00
Travis Wilson
a2e5ce2418 Make experimental capture work on Windows with read-write temp file behavior 2020-09-10 20:14:18 +02:00
Martin Hořeňovský
fd9f5ac661 v2.13.1 2020-09-07 12:34:55 +02:00
Dawid Kurek
f0dc4d9be0 Remove superfluous values
The `0`s were needed for the expansion of parameter pack for the sake of
expander. Now when we have `index++` it is no more needed.
2020-08-27 11:15:58 +02:00
Sean Middleditch
284672cc84 Support sentinel-based ranges in default stringify (#2004) 2020-08-18 10:34:47 +02:00
mattkurz
2b34b5c7d0 Fix typo in generators docs 2020-08-03 23:33:32 +02:00
Gregory Bond
708487d201 Issue 1992: Better c++17 std::byte detection
This fixed buld errors for ubuntu-16 + clang and similar situations
where C++17 is supported in the compiler but not the default
C++ standard library.
2020-08-03 14:38:56 +02:00
James Touton
6859c683e0 Don't apply global settings when configuring as a subproject. 2020-08-01 19:42:30 +02:00
Karthik Nishanth
de3a208e16 Update ParseAndAddCatchTests.cmake 2020-08-01 19:40:29 +02:00
Reinhold Gschweicher
229cc4823c Fix CMake add test helper for CMake 3.18.0
With CMake 3.18.0 the `add_test(NAME)` handling changed. The escaped
double quotes confuse the new call. Work around this upstream change.

fixes: https://github.com/catchorg/Catch2/issues/1984
2020-07-17 23:56:33 +02:00
Martin Hořeňovský
7f21cc6c55 v2.13.0 2020-07-12 20:28:38 +02:00
Martin Hořeňovský
4c85248179 Fixup whitespace in TAPReporter 2020-07-12 20:27:25 +02:00
Martin Hořeňovský
b4e2237152 Remove pointless CompactReporter::getPreferences override 2020-07-12 20:06:14 +02:00
Martin Hořeňovský
40937b67c7 Merge pull request #1983 from s7726/patch-1
Update catch_reporter_tap.hpp
2020-07-12 20:00:03 +02:00
Martin Hořeňovský
0d5b131394 Improve documentation for --min-duration 2020-07-12 16:27:55 +02:00
Martin Hořeňovský
ad3b90553b Document GENERATE's new usage between SECTIONs 2020-07-12 16:24:32 +02:00
Gavin S
b1c45652e5 Update catch_reporter_tap.hpp
TAP format requires all results to be reported.
Removed extraneous preferences function (handled by parent)
Incorporated fix from 3d9e7db2e0
Simplified total printing
2020-07-12 01:17:37 -07:00
Martin Hořeňovský
b79a83e4aa Modify generator tracking to allow GENERATEs between SECTIONs
This means that code such as

```cpp
TEST_CASE() {
    SECTION("first") { SUCCEED(); }
    auto _ = GENERATE(1, 2);
    SECTION("second") { SUCCEED(); }
}
```

will run and report 3 assertions, 1 from section "first" and 2
from section "second". This also applies for greater and potentially
more confusing nesting, but fundamentally it is up to the user to
avoid overly complex and confusing nestings, just as with `SECTION`s.

The old behaviour of `GENERATE` as first thing in a `TEST_CASE`,
`GENERATE` not followed by a `SECTION`, etc etc should be unchanged.

Closes #1938
2020-07-11 23:16:07 +02:00
Martin Hořeňovský
89fe35d515 Fix how testRandomOrder.py builds tag arguments 2020-07-11 21:32:10 +02:00
Martin Hořeňovský
115d6a1c40 Increase tolerances in --min-duration tests
The underpowered and oversubscribed CI servers are hell.
2020-07-07 11:36:56 +02:00
Martin Hořeňovský
91576352f9 Fixup single_include to be consistent with last tag
Closes #1975
2020-07-07 11:32:05 +02:00
Martin Hořeňovský
6f7c191513 --min-duration is overriden by -d no 2020-07-06 20:33:08 +02:00
Martin Hořeňovský
4eb9d37e05 Refactor tests for duration reporting threshold 2020-07-06 20:02:20 +02:00
John Bytheway
53d8af8e96 Test for --min-duration 2020-07-06 11:35:02 +02:00
John Bytheway
46fde0c597 Add --min-duration option
A test runner already has a --durations option to print durations.
However, this isn't entirely satisfactory.

When there are many tests, this produces output spam which makes it hard
to find the test failure output.  Nevertheless, it is helpful to be
informed of tests which are unusually slow.

Therefore, introduce a new option --min-duration that causes all
durations above a certain threshold to be printed.  This allows slow
tests to be visible without mentioning every test.
2020-07-06 11:35:02 +02:00
Martin Hořeňovský
de103db696 Merge pull request #1973 from echuber2/patch-1
Escaping "*" ("times") to fix Markdown presentation
2020-07-06 11:34:22 +02:00
Eric Huber
fedc3a7b7b Escaping literal "*" ("times") to fix markdown 2020-07-05 17:04:00 -05:00
Martin Hořeňovský
c299133a31 v2.12.4 2020-07-05 11:51:30 +02:00
Martin Hořeňovský
09b8017ea3 Update FUNDING file (-Patreon, +PayPal) 2020-07-04 20:06:27 +02:00
George Rhoten
bad3c93049 Fix for macOS on ARM 2020-07-01 19:28:50 +02:00
Martin Hořeňovský
0f05c034c2 v2.12.3 2020-06-29 20:50:39 +02:00
Ryan Pavlik
ee4538c0c6 Add OverallResultsCases element to XML reporter 2020-06-28 22:36:08 +02:00
Martin Hořeňovský
dc7a20fc74 Rewrite the contributing documentation 2020-06-27 17:44:08 +02:00
Martin Hořeňovský
018dc0b74f Replace a TODO comment in examples 2020-06-26 20:04:05 +02:00
Richard Ash
ad1940f336 Add an example of using GENERATE(table())
There are some examples on issue #850 of using this feature, but they
are not easily found from the documentation. Adding them here as an
example makes them more findable and ensures they keep working if the
API changes.
2020-06-23 22:55:03 +02:00
Richard Ash
5399921622 Add notes on compiling the examples.
This took me some time to figure out so document for others.
2020-06-20 21:41:10 +02:00
offa
e815acddf8 Clang-format configuration added.
Some notes on the configuration options chosen:

* We want `AllowShortEnumsOnASingleLine` set to `false`, but that
option is clang-format-11 and up, which is not out yet.
* `IndentPPDirectives` is currently inconsistent, but `AfterHash`
is the preferred style in new code.
* `NamespaceIndentation` is a mess, but `All` is closer to the effect
we want than `Inner`.
* `SpacesInParentheses` set to `true` is not ideal due to it also
introducing extra spaces in preprocessor expressions, but using it
is much closer to the current style than not.

All in all, using this setting globally would reformat pretty much
every line of code in the codebase, but it is as close as possible
to the bespoke style currently used. Still, it should only be used
on the diffs.

Closes #1182
2020-06-19 09:49:10 +02:00
Richard Ash
e7189f1e4f Make scripts/updateDocumentToC.py executable.
On systems where the file system has excute permissions, this script was
not marked as executable in a clean git checkout and so could be run
without first changing the permissions. Fixed by setting the relevant
git flag.
2020-06-18 21:28:08 +02:00
Martin Hořeňovský
1806b21545 Add explicit test for shortcircuiting behaviour of combined matchers 2020-06-14 21:48:08 +02:00
Martin Hořeňovský
288416f501 Devirtualize NameAndLocation query on trackers 2020-06-13 19:26:17 +02:00
Martin Hořeňovský
cbbebb65b6 Fix copy paste error in 7-arg TEMPLATE_TEST_CASE_SIG implementation
Closes #1954
2020-06-13 15:46:59 +02:00
Martin Hořeňovský
fb08596b1b Clarify documentation about nested generators
Closes #1947
2020-06-13 11:12:12 +02:00
Matthias Blankertz
0614a4acb3 Hide std::exception_ptr and friends if exceptions disabled
Some compilers, e.g. the Green Hills C++ compiler, react badly to the
appearance of std::exception_ptr, std::current_exception,
std::rethrow_exception and std::uncaught_exception(s). To allow usage of
Catch2 with these compilers when exceptions are disabled, hide the usage
of std::exception_ptr etc. when compiling with
CATCH_CONFIG_DISABLE_EXCEPTIONS.
2020-06-12 23:23:55 +02:00
Martin Hořeňovský
0f12995501 Fix compilation of examples 2020-06-01 21:27:58 +02:00
Martin Hořeňovský
0807fdb175 Replace stray tabs with spaces 2020-06-01 19:06:51 +02:00
Martin Hořeňovský
9500ded83b Improved generator tracking
* Successive executions of the same `GENERATE` macro (e.g. because
of a for loop) no longer lead to multiple nested generators.
* The same line can now contain multiple `GENERATE` macros without
issues.

Fixes #1913
2020-06-01 19:06:51 +02:00
bogdasar1985
6c6ebe374a fixing UB 2020-05-29 14:56:40 +02:00
Martin Hořeňovský
b1b5cb8122 v2.12.2 2020-05-25 15:13:18 +02:00
Martin Hořeňovský
77dc8cfc45 Really fix use of std::result_of when invoke_result is available
Closes #1934
2020-05-22 10:05:34 +02:00
Martin Hořeňovský
ddc9f4c61d Avoid using std::result_of when std::invoke_result is available
Closes #1934
2020-05-21 21:39:19 +02:00
Martin Hořeňovský
bed47374ce Remove obsolete comment in UnorderedEquals vector matcher 2020-05-18 14:29:50 +02:00
Valentin Tolmer
0e9bae1cdb Create a BUILD file for compatibility with bazel
With this change, it's much easier for bazel projects to depend on
Catch. They just need to add:
  - In the workspace:
  ```
http_archive(
    name = "com_github_catchorg_catch2",
    urls = ["https://github.com/catchorg/Catch2/archive/v2.12.1.tar.gz"],
    strip_prefix = "Catch2-2.12.1",
    sha256 = "e5635c082282ea518a8dd7ee89796c8026af8ea9068cd7402fb1615deacd91c3",
)
```
  Or the appropriate version/sha256.
  - For the tests, assuming that `test_main.cc` contains the
  `CATCH_CONFIG_MAIN`:
  ```
cc_library(
    name = "test_main",
    srcs = ["test_main.cc"],
    deps = ["@com_github_catchorg_catch2//:catch2"],
)
```
2020-05-17 13:18:22 +02:00
Martin Hořeňovský
f133277910 Add status attribute to JUnit's section reporting
This brings our output inline with GTest's. We do not handle skipped
tests properly, but that should be currently less important than
having the attribute exist with proper value for non-skipped tests.

Thanks @joda-01.

Closes #1899
2020-05-15 21:00:19 +02:00
Martin Hořeňovský
f764ee3d30 Document that user can only provide main in TU with CONFIG_RUNNER
Closes #1851
2020-05-15 15:57:27 +02:00
Natsu
c190061001 Fix compilation failure when using libstdc++10 (#1929)
The issue is caused by deleted `std::__detail::begin` declared in `bits/iterator_concepts.h`. This would be found by ADL, and because it is deleted, compilation would fail. This change makes it so that we SFINAE on `begin(std::declval<T>())` and `end(std::declval<T>())` being well-formed.
2020-05-15 11:30:12 +02:00
Billy Robert O'Neal III
b1dcdc5032 Fix invalid isspace call detected by PREfast
D:\vcpkg\toolsrc\include\catch2\catch.hpp(11285): warning C6330: 'char' passed as _Param_(1) when 'unsigned char' is required in call to 'isspace'.
D:\vcpkg\toolsrc\include\catch2\catch.hpp(11288): warning C6330: 'char' passed as _Param_(1) when 'unsigned char' is required in call to 'isspace'.

ISO/IEC 9899:2011:
"7.4 Character handling <ctype.h>"/1
[...] In all cases the argument is an int, the value of which shall be
representable as an unsigned char or shall equal the value of the macro
EOF. If the argument has any other value, the behavior is undefined.

This means if isspace was passed a character like ñ it could corrupt
memory without the static_cast to treat it as a positive value after
integral promotion (and C libraries commonly use the int index supplied
as a key into a table which result in out of bounds access if the
resulting int is negative).
2020-05-12 14:07:22 +02:00
Martin Hořeňovský
f0e596e252 Silence clang-tidy's hicpp-vararg (alias of coreguidelines vararg)
Ideally, clang-tidy would be smart that if one alias of a warning
is suppressed, then the other one is suppressed as well, but as of
right now, it isn't. This means that for now we have to suppress
both aliases of this warning. Opened upstream issue to fix this:
https://bugs.llvm.org/show_bug.cgi?id=45859

Obviously, ideally clang-tidy would also not warn that we are calling
a vararg function when it is an unevaluated magic builtin, but that
also is not happening right now and I opened an issue for it:
https://bugs.llvm.org/show_bug.cgi?id=45860

Closes #1921
2020-05-09 18:23:12 +02:00
Martin Hořeňovský
594cab31ed Upload conan releases to catch2 remote (instead of Catch2)
At some point we moved over to catch2:catchorg (notice lowercase `c`)
instead of Catch2:catchorg, but we kept uploading the released
packages to the upper-cased repository... Time to fix this, and then
merge them again.
2020-05-06 20:49:26 +02:00
Gareth Lloyd
89f5f84351 Provide path of the cmake scripts to conan 2020-04-23 18:11:41 +02:00
Martin Hořeňovský
2e61d38c7c v2.12.1
--- Fixes ---
* Vector matchers now support initializer list literals better

--- Improvements ---
* Added support for `^` (bitwise xor) to `CHECK` and `REQUIRE`
2020-04-21 19:30:38 +02:00
Martin Hořeňovský
5c9f09e94a Add support for bitwise xor to the decomposer 2020-04-21 19:27:12 +02:00
Martin Hořeňovský
f4fc2dab2c Fixup template type argument inference for vector matchers 2020-04-21 19:09:45 +02:00
Martin Hořeňovský
cfb6956698 v2.12.0
--- Improvements ---
* Running tests in random order (`--order rand`) has been reworked significantly (#1908)
  * Given same seed, all platforms now produce the same order
  * Given same seed, the relative order of tests does not change if you select only a subset of them
* Vector matchers support custom allocators (#1909)
* `|` and `&` (bitwise or and bitwise and) are now supported in `CHECK` and `REQUIRE`
  * The resulting type must be convertible to `bool`

--- Fixes ---
* Fixed computation of benchmarking column widths in ConsoleReporter (#1885, #1886)
* Suppressed clang-tidy's `cppcoreguidelines-pro-type-vararg` in assertions (#1901)
  * It was a false positive trigered by the new warning support workaround
* Fixed bug in test specification parser handling of OR'd patterns using escaping (#1905)

--- Miscellaneous ---
* Worked around IBM XL's codegen bug (#1907)
  * It would emit code for _destructors_ of temporaries in an unevaluated context
* Improved detection of stdlib's support for `std::uncaught_exceptions` (#1911)
2020-04-21 16:33:15 +02:00
khyperia
e59fc2c3b3 Fix build with CATCH_CONFIG_DISABLE_EXCEPTIONS enabled 2020-04-21 15:31:15 +02:00
Martin Hořeňovský
4e4171420d Support bitand and bitor in REQUIRE/CHECK
This means that bit-flag-like types with conversion to bool can be
asserted on, like so `REQUIRE(var & Flags::AddNewline)`.
2020-04-21 11:00:08 +02:00
Martin Hořeňovský
37cbf4a4fe Add more tests for test spec parser
Originally the tests were from #1912, but as it turned out, the issue
was somewhere else. Still, the inputs provided were interesting, so
they are now part of our test suite.
2020-04-17 21:19:18 +02:00
schallerr
38f897c887 Support custom allocators in vector Matchers (#1909) 2020-04-16 15:36:54 +02:00
Martin Hořeňovský
fa4a93e051 Update documentation for --order 2020-04-15 16:20:05 +02:00
John Else
6fbe5efc71 Use macro to determine whether std::uncaught_exceptions is available
Catch assumes std::uncaught_exceptions is available whenever C++17 is
available, but for macOS versions older than 10.12 this is not the case.

Instead of checking the C++ version, use a macro to check whether the
feature is available.
2020-04-14 23:03:58 +02:00
Martin Hořeňovský
bad0fb51f8 Refactor implementation of hashed random order test sorting 2020-04-14 16:39:48 +02:00
Martin Hořeňovský
a2fc7cf8c0 Randomize test for subset invariant random ordering of tests
Also removed the iterative checking that seeds 1-100 do not create
the same output, because it used too much runtime.
2020-04-14 16:38:10 +02:00
John Bytheway
da9e3eec65 Add test for consistent random ordering 2020-04-14 12:47:36 +02:00
John Bytheway
f696ab836b Change random test shuffling technique
Previously a random test ordering was obtained by applying std::shuffle
to the tests in declaration order.  This has two problems:

- It depends on the declaration order, so the order in which the tests
  will be run will be platform-specific.
- When trying to debug accidental inter-test dependencies, it is helpful
  to be able to find a minimal subset of tests which exhibits the issue.
  However, any change to the set of tests being run will completely
  change the test ordering, making it difficult or impossible to reduce
  the set of tests being run in any reasonably efficient manner.

Therefore, change the randomization approach to resolve both these
issues.

Generate a random value based on the user-provided RNG seed.  Convert
every test case to an integer by hashing a combination of that value
with the test name.  Sort the test cases by this integer.

The test names and RNG are platform-independent, so this should be
consistent across platforms.  Also, removing one test does not change
the integer value associated with the remaining tests, so they remain in
the same order.

To hash, use the FNV-1a hash, except with the basis being our randomly
selected value rather than the fixed basis set in the algorithm.  Cannot
use std::hash, because it is important that the result be
platform-independent.
2020-04-14 12:47:36 +02:00
Martin Hořeňovský
5d32ce26f4 Fix bug in test spec parser handling of escaping in ORed patterns
It did not clear out all of its internal state when switching from
one pattern to another, so when it should've escaped `,`, it took
its position from its position in the original user-provided string,
rather than its position in the current pattern.

Fixes #1905
2020-04-12 18:48:52 +02:00
Andrew Gaspar
035a062596 Remove usage of __builtin_constant_p under IBM XL 2020-04-10 20:55:23 +02:00
Moritz Haase
d399a308d0 Suppress clang-tidy warning about vararg usage in assertion macros
CATCH_INTERNAL_IGNORE_BUT_WARN() introduced with b7b346c triggers
clang-tidy warning 'cppcoreguidelines-pro-type-vararg' for every usage
of assertion macros like CHECK() and REQUIRE(). Silence it via NOLINT
in the '#if defined(__clang__)' block only, as clang-tidy honors those.
2020-04-02 20:45:57 +02:00
Phoebe
b8ce814ee6 Add vcpkg installation instructions (#1898)
* Add vcpkg installation instructions

* Add index
2020-03-31 19:12:10 +02:00
Mark Gillard
6260962108 Added toml++ to opensource-users.md 2020-03-29 14:21:57 +02:00
Mark Gillard
b4c8967ac5 Fix alphabetical ordering of opensource-users.md 2020-03-29 14:21:57 +02:00
pi1024e
7900fb3abb C-header updates 2020-03-28 18:00:42 +01:00
Invincible
01bdfe3312 Change PARSE_CATCH_TESTS_ADD_FIXTURE_IN_TEST_NAME conditional.
When no TEST_CASE_METHOD function, there is no fixture to get.
2020-03-27 09:55:06 +01:00
Joel Uckelman
e5c9a58d66 Fixed typo in "benchmark name" column width calculation. Closes #1885. 2020-03-26 10:31:35 +01:00
122 changed files with 5709 additions and 1535 deletions

25
.clang-format Normal file
View File

@@ -0,0 +1,25 @@
---
AccessModifierOffset: '-4'
AlignEscapedNewlines: Left
AllowAllConstructorInitializersOnNextLine: 'true'
BinPackArguments: 'false'
BinPackParameters: 'false'
BreakConstructorInitializers: AfterColon
ConstructorInitializerAllOnOneLineOrOnePerLine: 'true'
DerivePointerAlignment: 'false'
FixNamespaceComments: 'true'
IncludeBlocks: Regroup
IndentCaseLabels: 'false'
IndentPPDirectives: AfterHash
IndentWidth: '4'
Language: Cpp
NamespaceIndentation: All
PointerAlignment: Left
SpaceBeforeCtorInitializerColon: 'false'
SpaceInEmptyParentheses: 'false'
SpacesInParentheses: 'true'
Standard: Cpp11
TabWidth: '4'
UseTab: Never
...

View File

@@ -31,7 +31,7 @@ class BuilderSettings(object):
not match the stable pattern. Otherwise it will upload to stable not match the stable pattern. Otherwise it will upload to stable
channel. channel.
""" """
return os.getenv("CONAN_UPLOAD", "https://api.bintray.com/conan/catchorg/Catch2") return os.getenv("CONAN_UPLOAD", "https://api.bintray.com/conan/catchorg/catch2")
@property @property
def upload_only_when_stable(self): def upload_only_when_stable(self):

2
.github/FUNDING.yml vendored
View File

@@ -1 +1 @@
patreon: horenmar custom: "https://www.paypal.me/horenmar"

1
.gitignore vendored
View File

@@ -28,3 +28,4 @@ Build
cmake-build-* cmake-build-*
benchmark-dir benchmark-dir
.conan/test_package/build .conan/test_package/build
bazel-*

View File

@@ -258,6 +258,15 @@ matrix:
addons: *gcc7 addons: *gcc7
env: COMPILER='g++-7' EXAMPLES=1 COVERAGE=1 EXTRAS=1 CPP17=1 env: COMPILER='g++-7' EXAMPLES=1 COVERAGE=1 EXTRAS=1 CPP17=1
- os: linux
dist: xenial
compiler: clang
addons:
apt:
sources: *all_sources
packages: ['clang-5.0']
env: COMPILER='clang++-5.0' CPP17=1
- os: linux - os: linux
dist: xenial dist: xenial
compiler: clang compiler: clang
@@ -276,19 +285,6 @@ matrix:
packages: ['clang-6.0', 'libstdc++-8-dev'] packages: ['clang-6.0', 'libstdc++-8-dev']
env: COMPILER='clang++-6.0' CPP17=1 EXAMPLES=1 COVERAGE=1 EXTRAS=1 env: COMPILER='clang++-6.0' CPP17=1 EXAMPLES=1 COVERAGE=1 EXTRAS=1
# 8/ Conan
- language: python
python:
- "3.7"
dist: xenial
install:
- pip install conan-package-tools
env:
- CONAN_GCC_VERSIONS=8
- CONAN_DOCKER_IMAGE=conanio/gcc8
script:
- python .conan/build.py
install: install:
- DEPS_DIR="${TRAVIS_BUILD_DIR}/deps" - DEPS_DIR="${TRAVIS_BUILD_DIR}/deps"
- mkdir -p ${DEPS_DIR} && cd ${DEPS_DIR} - mkdir -p ${DEPS_DIR} && cd ${DEPS_DIR}

17
BUILD.bazel Normal file
View File

@@ -0,0 +1,17 @@
# Load the cc_library rule.
load("@rules_cc//cc:defs.bzl", "cc_library")
# Header-only rule to export catch2/catch.hpp.
cc_library(
name = "catch2",
hdrs = ["single_include/catch2/catch.hpp"],
includes = ["single_include/"],
visibility = ["//visibility:public"],
)
cc_library(
name = "catch2_with_main",
srcs = ["src/catch_with_main.cpp"],
visibility = ["//visibility:public"],
deps = ["//:catch2"],
)

View File

@@ -1,4 +1,7 @@
prefix=@CMAKE_INSTALL_PREFIX@
exec_prefix=${prefix}
includedir=@CMAKE_INSTALL_FULL_INCLUDEDIR@ includedir=@CMAKE_INSTALL_FULL_INCLUDEDIR@
libdir=@CMAKE_INSTALL_FULL_LIBDIR@
Name: Catch2 Name: Catch2
Description: A modern, C++-native, header-only, test framework for C++11 Description: A modern, C++-native, header-only, test framework for C++11

View File

@@ -3,7 +3,9 @@ cmake_minimum_required(VERSION 3.5)
# detect if Catch is being bundled, # detect if Catch is being bundled,
# disable testsuite in that case # disable testsuite in that case
if(NOT DEFINED PROJECT_NAME) if(NOT DEFINED PROJECT_NAME)
set(NOT_SUBPROJECT ON) set(NOT_SUBPROJECT ON)
else()
set(NOT_SUBPROJECT OFF)
endif() endif()
# Catch2's build breaks if done in-tree. You probably should not build # Catch2's build breaks if done in-tree. You probably should not build
@@ -14,27 +16,23 @@ if (CMAKE_BINARY_DIR STREQUAL CMAKE_CURRENT_SOURCE_DIR)
endif() endif()
project(Catch2 LANGUAGES CXX VERSION 2.11.3) project(Catch2 LANGUAGES CXX VERSION 2.13.8)
# 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")
include(GNUInstallDirs) include(GNUInstallDirs)
include(CMakePackageConfigHelpers)
include(CTest)
option(CATCH_USE_VALGRIND "Perform SelfTests with Valgrind" OFF) option(CATCH_USE_VALGRIND "Perform SelfTests with Valgrind" OFF)
option(CATCH_BUILD_TESTING "Build SelfTest project" ON) option(CATCH_BUILD_TESTING "Build SelfTest project" ON)
option(CATCH_BUILD_EXAMPLES "Build documentation examples" OFF) option(CATCH_BUILD_EXAMPLES "Build documentation examples" OFF)
option(CATCH_BUILD_EXTRA_TESTS "Build extra tests" OFF) option(CATCH_BUILD_EXTRA_TESTS "Build extra tests" OFF)
option(CATCH_BUILD_STATIC_LIBRARY "Builds static library from the main implementation. EXPERIMENTAL" OFF)
option(CATCH_ENABLE_COVERAGE "Generate coverage for codecov.io" OFF) option(CATCH_ENABLE_COVERAGE "Generate coverage for codecov.io" OFF)
option(CATCH_ENABLE_WERROR "Enable all warnings as errors" ON) option(CATCH_ENABLE_WERROR "Enable all warnings as errors" ON)
option(CATCH_INSTALL_DOCS "Install documentation alongside library" ON) option(CATCH_INSTALL_DOCS "Install documentation alongside library" ON)
option(CATCH_INSTALL_HELPERS "Install contrib alongside library" ON) option(CATCH_INSTALL_HELPERS "Install contrib alongside library" ON)
set_property(GLOBAL PROPERTY USE_FOLDERS ON)
# define some folders # define some folders
set(CATCH_DIR ${CMAKE_CURRENT_SOURCE_DIR}) set(CATCH_DIR ${CMAKE_CURRENT_SOURCE_DIR})
set(SELF_TEST_DIR ${CATCH_DIR}/projects/SelfTest) set(SELF_TEST_DIR ${CATCH_DIR}/projects/SelfTest)
@@ -45,12 +43,16 @@ if(USE_WMAIN)
set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} /ENTRY:wmainCRTStartup") set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} /ENTRY:wmainCRTStartup")
endif() endif()
if (BUILD_TESTING AND CATCH_BUILD_TESTING AND NOT_SUBPROJECT) if(NOT_SUBPROJECT)
find_package(PythonInterp) include(CTest)
if (NOT PYTHONINTERP_FOUND) set_property(GLOBAL PROPERTY USE_FOLDERS ON)
message(FATAL_ERROR "Python not found, but required for tests") if(BUILD_TESTING AND CATCH_BUILD_TESTING)
find_package(PythonInterp)
if (NOT PYTHONINTERP_FOUND)
message(FATAL_ERROR "Python not found, but required for tests")
endif()
add_subdirectory(projects)
endif() endif()
add_subdirectory(projects)
endif() endif()
if(CATCH_BUILD_EXAMPLES) if(CATCH_BUILD_EXAMPLES)
@@ -103,10 +105,24 @@ endif()
# provide a namespaced alias for clients to 'link' against if catch is included as a sub-project # provide a namespaced alias for clients to 'link' against if catch is included as a sub-project
add_library(Catch2::Catch2 ALIAS Catch2) add_library(Catch2::Catch2 ALIAS Catch2)
# Hacky support for compiling the impl into a static lib
if (CATCH_BUILD_STATIC_LIBRARY)
add_library(Catch2WithMain ${CMAKE_CURRENT_LIST_DIR}/src/catch_with_main.cpp)
target_link_libraries(Catch2WithMain PUBLIC Catch2)
add_library(Catch2::Catch2WithMain ALIAS Catch2WithMain)
# Make the build reproducible on versions of g++ and clang that supports -ffile-prefix-map
if(("${CMAKE_CXX_COMPILER_ID}" STREQUAL "GNU" AND NOT ${CMAKE_CXX_COMPILER_VERSION} VERSION_LESS 8) OR
("${CMAKE_CXX_COMPILER_ID}" STREQUAL "Clang" AND NOT ${CMAKE_CXX_COMPILER_VERSION} VERSION_LESS 10))
target_compile_options(Catch2WithMain PRIVATE "-ffile-prefix-map=${CMAKE_SOURCE_DIR}=.")
endif()
endif(CATCH_BUILD_STATIC_LIBRARY)
# Only perform the installation steps when Catch is not being used as # Only perform the installation steps when Catch is not being used as
# a subproject via `add_subdirectory`, or the destinations will break, # a subproject via `add_subdirectory`, or the destinations will break,
# see https://github.com/catchorg/Catch2/issues/1373 # see https://github.com/catchorg/Catch2/issues/1373
if (NOT_SUBPROJECT) if (NOT_SUBPROJECT)
include(CMakePackageConfigHelpers)
set(CATCH_CMAKE_CONFIG_DESTINATION "${CMAKE_INSTALL_LIBDIR}/cmake/Catch2") set(CATCH_CMAKE_CONFIG_DESTINATION "${CMAKE_INSTALL_LIBDIR}/cmake/Catch2")
configure_package_config_file( configure_package_config_file(
@@ -116,11 +132,17 @@ if (NOT_SUBPROJECT)
${CATCH_CMAKE_CONFIG_DESTINATION} ${CATCH_CMAKE_CONFIG_DESTINATION}
) )
# Workaround lack of generator expressions in install(TARGETS
set(InstallationTargets Catch2)
if (TARGET Catch2WithMain)
list(APPEND InstallationTargets Catch2WithMain)
endif()
# create and install an export set for catch target as Catch2::Catch # create and install an export set for catch target as Catch2::Catch
install( install(
TARGETS TARGETS
Catch2 ${InstallationTargets}
EXPORT EXPORT
Catch2Targets Catch2Targets
DESTINATION DESTINATION

View File

@@ -2,14 +2,14 @@
![catch logo](artwork/catch2-logo-small.png) ![catch logo](artwork/catch2-logo-small.png)
[![Github Releases](https://img.shields.io/github/release/catchorg/catch2.svg)](https://github.com/catchorg/catch2/releases) [![Github Releases](https://img.shields.io/github/release/catchorg/catch2.svg)](https://github.com/catchorg/catch2/releases)
[![Build Status](https://travis-ci.org/catchorg/Catch2.svg?branch=master)](https://travis-ci.org/catchorg/Catch2) [![Build Status](https://travis-ci.org/catchorg/Catch2.svg?branch=v2.x)](https://travis-ci.org/catchorg/Catch2)
[![Build status](https://ci.appveyor.com/api/projects/status/github/catchorg/Catch2?svg=true)](https://ci.appveyor.com/project/catchorg/catch2) [![Build status](https://ci.appveyor.com/api/projects/status/github/catchorg/Catch2?svg=true)](https://ci.appveyor.com/project/catchorg/catch2)
[![codecov](https://codecov.io/gh/catchorg/Catch2/branch/master/graph/badge.svg)](https://codecov.io/gh/catchorg/Catch2) [![codecov](https://codecov.io/gh/catchorg/Catch2/branch/v2.x/graph/badge.svg)](https://codecov.io/gh/catchorg/Catch2)
[![Try online](https://img.shields.io/badge/try-online-blue.svg)](https://wandbox.org/permlink/p9Pcgple8QWwgNR0) [![Try online](https://img.shields.io/badge/try-online-blue.svg)](https://wandbox.org/permlink/6JUH8Eybx4CtvkJS)
[![Join the chat in Discord: https://discord.gg/4CWS9zD](https://img.shields.io/badge/Discord-Chat!-brightgreen.svg)](https://discord.gg/4CWS9zD) [![Join the chat in Discord: https://discord.gg/4CWS9zD](https://img.shields.io/badge/Discord-Chat!-brightgreen.svg)](https://discord.gg/4CWS9zD)
<a href="https://github.com/catchorg/Catch2/releases/download/v2.11.3/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.13.8/catch.hpp">The latest version of the single header can be downloaded directly using this link</a>
## Catch2 is released! ## Catch2 is released!

0
WORKSPACE Normal file
View File

View File

@@ -19,7 +19,7 @@ coverage:
codecov: codecov:
branch: master branch: v2.x
comment: comment:
layout: "diff" layout: "diff"

View File

@@ -10,7 +10,7 @@ class CatchConan(ConanFile):
homepage = url homepage = url
license = "BSL-1.0" license = "BSL-1.0"
exports = "LICENSE.txt" exports = "LICENSE.txt"
exports_sources = ("single_include/*", "CMakeLists.txt", "CMake/*", "contrib/*") exports_sources = ("single_include/*", "CMakeLists.txt", "CMake/*", "contrib/*", "src/*")
generators = "cmake" generators = "cmake"
def package(self): def package(self):
@@ -25,3 +25,6 @@ class CatchConan(ConanFile):
def package_id(self): def package_id(self):
self.info.header_only() self.info.header_only()
def package_info(self):
self.cpp_info.builddirs.append("lib/cmake/Catch2")

View File

@@ -33,6 +33,10 @@ same as the Catch name; see also ``TEST_PREFIX`` and ``TEST_SUFFIX``.
[TEST_SUFFIX suffix] [TEST_SUFFIX suffix]
[PROPERTIES name1 value1...] [PROPERTIES name1 value1...]
[TEST_LIST var] [TEST_LIST var]
[REPORTER reporter]
[OUTPUT_DIR dir]
[OUTPUT_PREFIX prefix}
[OUTPUT_SUFFIX suffix]
) )
``catch_discover_tests`` sets up a post-build command on the test executable ``catch_discover_tests`` sets up a post-build command on the test executable
@@ -90,6 +94,28 @@ same as the Catch name; see also ``TEST_PREFIX`` and ``TEST_SUFFIX``.
executable is being used in multiple calls to ``catch_discover_tests()``. executable is being used in multiple calls to ``catch_discover_tests()``.
Note that this variable is only available in CTest. Note that this variable is only available in CTest.
``REPORTER reporter``
Use the specified reporter when running the test case. The reporter will
be passed to the Catch executable as ``--reporter reporter``.
``OUTPUT_DIR dir``
If specified, the parameter is passed along as
``--out dir/<test_name>`` to Catch executable. The actual file name is the
same as the test name. This should be used instead of
``EXTRA_ARGS --out foo`` to avoid race conditions writing the result output
when using parallel test execution.
``OUTPUT_PREFIX prefix``
May be used in conjunction with ``OUTPUT_DIR``.
If specified, ``prefix`` is added to each output file name, like so
``--out dir/prefix<test_name>``.
``OUTPUT_SUFFIX suffix``
May be used in conjunction with ``OUTPUT_DIR``.
If specified, ``suffix`` is added to each output file name, like so
``--out dir/<test_name>suffix``. This can be used to add a file extension to
the output e.g. ".xml".
#]=======================================================================] #]=======================================================================]
#------------------------------------------------------------------------------ #------------------------------------------------------------------------------
@@ -97,7 +123,7 @@ function(catch_discover_tests TARGET)
cmake_parse_arguments( cmake_parse_arguments(
"" ""
"" ""
"TEST_PREFIX;TEST_SUFFIX;WORKING_DIRECTORY;TEST_LIST" "TEST_PREFIX;TEST_SUFFIX;WORKING_DIRECTORY;TEST_LIST;REPORTER;OUTPUT_DIR;OUTPUT_PREFIX;OUTPUT_SUFFIX"
"TEST_SPEC;EXTRA_ARGS;PROPERTIES" "TEST_SPEC;EXTRA_ARGS;PROPERTIES"
${ARGN} ${ARGN}
) )
@@ -110,7 +136,7 @@ function(catch_discover_tests TARGET)
endif() endif()
## Generate a unique name based on the extra arguments ## Generate a unique name based on the extra arguments
string(SHA1 args_hash "${_TEST_SPEC} ${_EXTRA_ARGS}") string(SHA1 args_hash "${_TEST_SPEC} ${_EXTRA_ARGS} ${_REPORTER} ${_OUTPUT_DIR} ${_OUTPUT_PREFIX} ${_OUTPUT_SUFFIX}")
string(SUBSTRING ${args_hash} 0 7 args_hash) string(SUBSTRING ${args_hash} 0 7 args_hash)
# Define rule to generate test list for aforementioned test executable # Define rule to generate test list for aforementioned test executable
@@ -134,6 +160,10 @@ function(catch_discover_tests TARGET)
-D "TEST_PREFIX=${_TEST_PREFIX}" -D "TEST_PREFIX=${_TEST_PREFIX}"
-D "TEST_SUFFIX=${_TEST_SUFFIX}" -D "TEST_SUFFIX=${_TEST_SUFFIX}"
-D "TEST_LIST=${_TEST_LIST}" -D "TEST_LIST=${_TEST_LIST}"
-D "TEST_REPORTER=${_REPORTER}"
-D "TEST_OUTPUT_DIR=${_OUTPUT_DIR}"
-D "TEST_OUTPUT_PREFIX=${_OUTPUT_PREFIX}"
-D "TEST_OUTPUT_SUFFIX=${_OUTPUT_SUFFIX}"
-D "CTEST_FILE=${ctest_tests_file}" -D "CTEST_FILE=${ctest_tests_file}"
-P "${_CATCH_DISCOVER_TESTS_SCRIPT}" -P "${_CATCH_DISCOVER_TESTS_SCRIPT}"
VERBATIM VERBATIM
@@ -172,4 +202,5 @@ endfunction()
set(_CATCH_DISCOVER_TESTS_SCRIPT set(_CATCH_DISCOVER_TESTS_SCRIPT
${CMAKE_CURRENT_LIST_DIR}/CatchAddTests.cmake ${CMAKE_CURRENT_LIST_DIR}/CatchAddTests.cmake
CACHE INTERNAL "Catch2 full path to CatchAddTests.cmake helper file"
) )

View File

@@ -6,13 +6,20 @@ set(suffix "${TEST_SUFFIX}")
set(spec ${TEST_SPEC}) set(spec ${TEST_SPEC})
set(extra_args ${TEST_EXTRA_ARGS}) set(extra_args ${TEST_EXTRA_ARGS})
set(properties ${TEST_PROPERTIES}) set(properties ${TEST_PROPERTIES})
set(reporter ${TEST_REPORTER})
set(output_dir ${TEST_OUTPUT_DIR})
set(output_prefix ${TEST_OUTPUT_PREFIX})
set(output_suffix ${TEST_OUTPUT_SUFFIX})
set(script) set(script)
set(suite) set(suite)
set(tests) set(tests)
function(add_command NAME) function(add_command NAME)
set(_args "") set(_args "")
foreach(_arg ${ARGN}) # use ARGV* instead of ARGN, because ARGN splits arrays into multiple arguments
math(EXPR _last_arg ${ARGC}-1)
foreach(_n RANGE 1 ${_last_arg})
set(_arg "${ARGV${_n}}")
if(_arg MATCHES "[^-./:a-zA-Z0-9_]") if(_arg MATCHES "[^-./:a-zA-Z0-9_]")
set(_args "${_args} [==[${_arg}]==]") # form a bracket_argument set(_args "${_args} [==[${_arg}]==]") # form a bracket_argument
else() else()
@@ -32,6 +39,7 @@ execute_process(
COMMAND ${TEST_EXECUTOR} "${TEST_EXECUTABLE}" ${spec} --list-test-names-only COMMAND ${TEST_EXECUTOR} "${TEST_EXECUTABLE}" ${spec} --list-test-names-only
OUTPUT_VARIABLE output OUTPUT_VARIABLE output
RESULT_VARIABLE result RESULT_VARIABLE result
WORKING_DIRECTORY "${TEST_WORKING_DIR}"
) )
# Catch --list-test-names-only reports the number of tests, so 0 is... surprising # Catch --list-test-names-only reports the number of tests, so 0 is... surprising
if(${result} EQUAL 0) if(${result} EQUAL 0)
@@ -48,6 +56,44 @@ endif()
string(REPLACE "\n" ";" output "${output}") string(REPLACE "\n" ";" output "${output}")
# Run test executable to get list of available reporters
execute_process(
COMMAND ${TEST_EXECUTOR} "${TEST_EXECUTABLE}" ${spec} --list-reporters
OUTPUT_VARIABLE reporters_output
RESULT_VARIABLE reporters_result
WORKING_DIRECTORY "${TEST_WORKING_DIR}"
)
if(${reporters_result} EQUAL 0)
message(WARNING
"Test executable '${TEST_EXECUTABLE}' contains no reporters!\n"
)
elseif(${reporters_result} LESS 0)
message(FATAL_ERROR
"Error running test executable '${TEST_EXECUTABLE}':\n"
" Result: ${reporters_result}\n"
" Output: ${reporters_output}\n"
)
endif()
string(FIND "${reporters_output}" "${reporter}" reporter_is_valid)
if(reporter AND ${reporter_is_valid} EQUAL -1)
message(FATAL_ERROR
"\"${reporter}\" is not a valid reporter!\n"
)
endif()
# Prepare reporter
if(reporter)
set(reporter_arg "--reporter ${reporter}")
endif()
# Prepare output dir
if(output_dir AND NOT IS_ABSOLUTE ${output_dir})
set(output_dir "${TEST_WORKING_DIR}/${output_dir}")
if(NOT EXISTS ${output_dir})
file(MAKE_DIRECTORY ${output_dir})
endif()
endif()
# Parse output # Parse output
foreach(line ${output}) foreach(line ${output})
set(test ${line}) set(test ${line})
@@ -56,6 +102,12 @@ foreach(line ${output})
foreach(char , [ ]) foreach(char , [ ])
string(REPLACE ${char} "\\${char}" test_name ${test_name}) string(REPLACE ${char} "\\${char}" test_name ${test_name})
endforeach(char) endforeach(char)
# ...add output dir
if(output_dir)
string(REGEX REPLACE "[^A-Za-z0-9_]" "_" test_name_clean ${test_name})
set(output_dir_arg "--out ${output_dir}/${output_prefix}${test_name_clean}${output_suffix}")
endif()
# ...and add to script # ...and add to script
add_command(add_test add_command(add_test
"${prefix}${test}${suffix}" "${prefix}${test}${suffix}"
@@ -63,6 +115,8 @@ foreach(line ${output})
"${TEST_EXECUTABLE}" "${TEST_EXECUTABLE}"
"${test_name}" "${test_name}"
${extra_args} ${extra_args}
"${reporter_arg}"
"${output_dir_arg}"
) )
add_command(set_tests_properties add_command(set_tests_properties
"${prefix}${test}${suffix}" "${prefix}${test}${suffix}"

View File

@@ -1,9 +1,11 @@
#==================================================================================================# #==================================================================================================#
# supported macros # # supported macros #
# - TEST_CASE, # # - TEST_CASE, #
# - TEMPLATE_TEST_CASE #
# - SCENARIO, # # - SCENARIO, #
# - TEST_CASE_METHOD, # # - TEST_CASE_METHOD, #
# - CATCH_TEST_CASE, # # - CATCH_TEST_CASE, #
# - CATCH_TEMPLATE_TEST_CASE #
# - CATCH_SCENARIO, # # - CATCH_SCENARIO, #
# - CATCH_TEST_CASE_METHOD. # # - CATCH_TEST_CASE_METHOD. #
# # # #
@@ -106,7 +108,8 @@ function(ParseAndAddCatchTests_ParseFile SourceFile TestTarget)
ParseAndAddCatchTests_RemoveComments(Contents) ParseAndAddCatchTests_RemoveComments(Contents)
# Find definition of test names # Find definition of test names
string(REGEX MATCHALL "[ \t]*(CATCH_)?(TEST_CASE_METHOD|SCENARIO|TEST_CASE)[ \t]*\\([^\)]+\\)+[ \t\n]*{+[ \t]*(//[^\n]*[Tt][Ii][Mm][Ee][Oo][Uu][Tt][ \t]*[0-9]+)*" Tests "${Contents}") # https://regex101.com/r/JygOND/1
string(REGEX MATCHALL "[ \t]*(CATCH_)?(TEMPLATE_)?(TEST_CASE_METHOD|SCENARIO|TEST_CASE)[ \t]*\\([ \t\n]*\"[^\"]*\"[ \t\n]*(,[ \t\n]*\"[^\"]*\")?(,[ \t\n]*[^\,\)]*)*\\)[ \t\n]*\{+[ \t]*(//[^\n]*[Tt][Ii][Mm][Ee][Oo][Uu][Tt][ \t]*[0-9]+)*" Tests "${Contents}")
if(PARSE_CATCH_TESTS_ADD_TO_CONFIGURE_DEPENDS AND Tests) if(PARSE_CATCH_TESTS_ADD_TO_CONFIGURE_DEPENDS AND Tests)
ParseAndAddCatchTests_PrintDebugMessage("Adding ${SourceFile} to CMAKE_CONFIGURE_DEPENDS property") ParseAndAddCatchTests_PrintDebugMessage("Adding ${SourceFile} to CMAKE_CONFIGURE_DEPENDS property")
@@ -117,13 +120,21 @@ function(ParseAndAddCatchTests_ParseFile SourceFile TestTarget)
) )
endif() endif()
# check CMP0110 policy for new add_test() behavior
if(POLICY CMP0110)
cmake_policy(GET CMP0110 _cmp0110_value) # new add_test() behavior
else()
# just to be thorough explicitly set the variable
set(_cmp0110_value)
endif()
foreach(TestName ${Tests}) foreach(TestName ${Tests})
# Strip newlines # Strip newlines
string(REGEX REPLACE "\\\\\n|\n" "" TestName "${TestName}") string(REGEX REPLACE "\\\\\n|\n" "" TestName "${TestName}")
# Get test type and fixture if applicable # Get test type and fixture if applicable
string(REGEX MATCH "(CATCH_)?(TEST_CASE_METHOD|SCENARIO|TEST_CASE)[ \t]*\\([^,^\"]*" TestTypeAndFixture "${TestName}") string(REGEX MATCH "(CATCH_)?(TEMPLATE_)?(TEST_CASE_METHOD|SCENARIO|TEST_CASE)[ \t]*\\([^,^\"]*" TestTypeAndFixture "${TestName}")
string(REGEX MATCH "(CATCH_)?(TEST_CASE_METHOD|SCENARIO|TEST_CASE)" TestType "${TestTypeAndFixture}") string(REGEX MATCH "(CATCH_)?(TEMPLATE_)?(TEST_CASE_METHOD|SCENARIO|TEST_CASE)" TestType "${TestTypeAndFixture}")
string(REGEX REPLACE "${TestType}\\([ \t]*" "" TestFixture "${TestTypeAndFixture}") string(REGEX REPLACE "${TestType}\\([ \t]*" "" TestFixture "${TestTypeAndFixture}")
# Get string parts of test definition # Get string parts of test definition
@@ -144,7 +155,7 @@ function(ParseAndAddCatchTests_ParseFile SourceFile TestTarget)
if("${TestType}" STREQUAL "SCENARIO") if("${TestType}" STREQUAL "SCENARIO")
set(Name "Scenario: ${Name}") set(Name "Scenario: ${Name}")
endif() endif()
if(PARSE_CATCH_TESTS_ADD_FIXTURE_IN_TEST_NAME AND TestFixture) if(PARSE_CATCH_TESTS_ADD_FIXTURE_IN_TEST_NAME AND "${TestType}" MATCHES "(CATCH_)?TEST_CASE_METHOD" AND TestFixture )
set(CTestName "${TestFixture}:${Name}") set(CTestName "${TestFixture}:${Name}")
else() else()
set(CTestName "${Name}") set(CTestName "${Name}")
@@ -189,24 +200,39 @@ function(ParseAndAddCatchTests_ParseFile SourceFile TestTarget)
# Escape commas in the test spec # Escape commas in the test spec
string(REPLACE "," "\\," Name ${Name}) string(REPLACE "," "\\," Name ${Name})
# Work around CMake 3.18.0 change in `add_test()`, before the escaped quotes were necessary,
# only with CMake 3.18.0 the escaped double quotes confuse the call. This change is reverted in 3.18.1
# And properly introduced in 3.19 with the CMP0110 policy
if(_cmp0110_value STREQUAL "NEW" OR ${CMAKE_VERSION} VERSION_EQUAL "3.18")
ParseAndAddCatchTests_PrintDebugMessage("CMP0110 set to NEW, no need for add_test(\"\") workaround")
else()
ParseAndAddCatchTests_PrintDebugMessage("CMP0110 set to OLD adding \"\" for add_test() workaround")
set(CTestName "\"${CTestName}\"")
endif()
# Handle template test cases
if("${TestTypeAndFixture}" MATCHES ".*TEMPLATE_.*")
set(Name "${Name} - *")
endif()
# Add the test and set its properties # Add the test and set its properties
add_test(NAME "\"${CTestName}\"" COMMAND ${OptionalCatchTestLauncher} $<TARGET_FILE:${TestTarget}> ${Name} ${AdditionalCatchParameters}) add_test(NAME "${CTestName}" COMMAND ${OptionalCatchTestLauncher} $<TARGET_FILE:${TestTarget}> ${Name} ${AdditionalCatchParameters})
# Old CMake versions do not document VERSION_GREATER_EQUAL, so we use VERSION_GREATER with 3.8 instead # Old CMake versions do not document VERSION_GREATER_EQUAL, so we use VERSION_GREATER with 3.8 instead
if(PARSE_CATCH_TESTS_NO_HIDDEN_TESTS AND ${HiddenTagFound} AND ${CMAKE_VERSION} VERSION_GREATER "3.8") if(PARSE_CATCH_TESTS_NO_HIDDEN_TESTS AND ${HiddenTagFound} AND ${CMAKE_VERSION} VERSION_GREATER "3.8")
ParseAndAddCatchTests_PrintDebugMessage("Setting DISABLED test property") ParseAndAddCatchTests_PrintDebugMessage("Setting DISABLED test property")
set_tests_properties("\"${CTestName}\"" PROPERTIES DISABLED ON) set_tests_properties("${CTestName}" PROPERTIES DISABLED ON)
else() else()
set_tests_properties("\"${CTestName}\"" PROPERTIES FAIL_REGULAR_EXPRESSION "No tests ran" set_tests_properties("${CTestName}" PROPERTIES FAIL_REGULAR_EXPRESSION "No tests ran"
LABELS "${Labels}") LABELS "${Labels}")
endif() endif()
set_property( set_property(
TARGET ${TestTarget} TARGET ${TestTarget}
APPEND APPEND
PROPERTY ParseAndAddCatchTests_TESTS "\"${CTestName}\"") PROPERTY ParseAndAddCatchTests_TESTS "${CTestName}")
set_property( set_property(
SOURCE ${SourceFile} SOURCE ${SourceFile}
APPEND APPEND
PROPERTY ParseAndAddCatchTests_TESTS "\"${CTestName}\"") PROPERTY ParseAndAddCatchTests_TESTS "${CTestName}")
endif() endif()
@@ -215,6 +241,7 @@ endfunction()
# entry point # entry point
function(ParseAndAddCatchTests TestTarget) function(ParseAndAddCatchTests TestTarget)
message(DEPRECATION "ParseAndAddCatchTest: function deprecated because of possibility of missed test cases. Consider using 'catch_discover_tests' from 'Catch.cmake'")
ParseAndAddCatchTests_PrintDebugMessage("Started parsing ${TestTarget}") ParseAndAddCatchTests_PrintDebugMessage("Started parsing ${TestTarget}")
get_target_property(SourceFiles ${TestTarget} SOURCES) get_target_property(SourceFiles ${TestTarget} SOURCES)
ParseAndAddCatchTests_PrintDebugMessage("Found the following sources: ${SourceFiles}") ParseAndAddCatchTests_PrintDebugMessage("Found the following sources: ${SourceFiles}")

View File

@@ -6,6 +6,7 @@
[Automatic test registration](#automatic-test-registration)<br> [Automatic test registration](#automatic-test-registration)<br>
[CMake project options](#cmake-project-options)<br> [CMake project options](#cmake-project-options)<br>
[Installing Catch2 from git repository](#installing-catch2-from-git-repository)<br> [Installing Catch2 from git repository](#installing-catch2-from-git-repository)<br>
[Installing Catch2 from vcpkg](#installing-catch2-from-vcpkg)<br>
Because we use CMake to build Catch2, we also provide a couple of Because we use CMake to build Catch2, we also provide a couple of
integration points for our users. integration points for our users.
@@ -35,6 +36,20 @@ add_subdirectory(lib/Catch2)
target_link_libraries(tests Catch2::Catch2) target_link_libraries(tests Catch2::Catch2)
``` ```
Another possibility is to use [FetchContent](https://cmake.org/cmake/help/latest/module/FetchContent.html):
```cmake
Include(FetchContent)
FetchContent_Declare(
Catch2
GIT_REPOSITORY https://github.com/catchorg/Catch2.git
GIT_TAG v2.13.1)
FetchContent_MakeAvailable(Catch2)
target_link_libraries(tests Catch2::Catch2)
```
## Automatic test registration ## Automatic test registration
Catch2's repository also contains two CMake scripts that help users Catch2's repository also contains two CMake scripts that help users
@@ -42,7 +57,7 @@ with automatically registering their `TEST_CASE`s with CTest. They
can be found in the `contrib` folder, and are can be found in the `contrib` folder, and are
1) `Catch.cmake` (and its dependency `CatchAddTests.cmake`) 1) `Catch.cmake` (and its dependency `CatchAddTests.cmake`)
2) `ParseAndAddCatchTests.cmake` 2) `ParseAndAddCatchTests.cmake` (deprecated)
If Catch2 has been installed in system, both of these can be used after If Catch2 has been installed in system, both of these can be used after
doing `find_package(Catch2 REQUIRED)`. Otherwise you need to add them doing `find_package(Catch2 REQUIRED)`. Otherwise you need to add them
@@ -82,6 +97,10 @@ catch_discover_tests(target
[TEST_SUFFIX suffix] [TEST_SUFFIX suffix]
[PROPERTIES name1 value1...] [PROPERTIES name1 value1...]
[TEST_LIST var] [TEST_LIST var]
[REPORTER reporter]
[OUTPUT_DIR dir]
[OUTPUT_PREFIX prefix]
[OUTPUT_SUFFIX suffix]
) )
``` ```
@@ -128,13 +147,46 @@ default `<target>_TESTS`. This can be useful when the same test
executable is being used in multiple calls to `catch_discover_tests()`. executable is being used in multiple calls to `catch_discover_tests()`.
Note that this variable is only available in CTest. Note that this variable is only available in CTest.
* `REPORTER reporter`
Use the specified reporter when running the test case. The reporter will
be passed to the test runner as `--reporter reporter`.
* `OUTPUT_DIR dir`
If specified, the parameter is passed along as
`--out dir/<test_name>` to test executable. The actual file name is the
same as the test name. This should be used instead of
`EXTRA_ARGS --out foo` to avoid race conditions writing the result output
when using parallel test execution.
* `OUTPUT_PREFIX prefix`
May be used in conjunction with `OUTPUT_DIR`.
If specified, `prefix` is added to each output file name, like so
`--out dir/prefix<test_name>`.
* `OUTPUT_SUFFIX suffix`
May be used in conjunction with `OUTPUT_DIR`.
If specified, `suffix` is added to each output file name, like so
`--out dir/<test_name>suffix`. This can be used to add a file extension to
the output file name e.g. ".xml".
### `ParseAndAddCatchTests.cmake` ### `ParseAndAddCatchTests.cmake`
⚠ This script is [deprecated](https://github.com/catchorg/Catch2/pull/2120)
in Catch 2.13.4 and superseded by the above approach using `catch_discover_tests`.
See [#2092](https://github.com/catchorg/Catch2/issues/2092) for details.
`ParseAndAddCatchTests` works by parsing all implementation files `ParseAndAddCatchTests` works by parsing all implementation files
associated with the provided target, and registering them via CTest's associated with the provided target, and registering them via CTest's
`add_test`. This approach has some limitations, such as the fact that `add_test`. This approach has some limitations, such as the fact that
commented-out tests will be registered anyway. commented-out tests will be registered anyway. More serious, only a
subset of the assertion macros currently available in Catch can be
detected by this script and tests with any macros that cannot be
parsed are *silently ignored*.
#### Usage #### Usage
@@ -220,6 +272,19 @@ when configuring the build, and then modify your calls to
[find_package](https://cmake.org/cmake/help/latest/command/find_package.html) [find_package](https://cmake.org/cmake/help/latest/command/find_package.html)
accordingly. accordingly.
## Installing Catch2 from vcpkg
Alternatively, you can build and install Catch2 using [vcpkg](https://github.com/microsoft/vcpkg/) dependency manager:
```
git clone https://github.com/Microsoft/vcpkg.git
cd vcpkg
./bootstrap-vcpkg.sh
./vcpkg integrate install
./vcpkg install catch2
```
The catch2 port in vcpkg is kept up to date by microsoft team members and community contributors.
If the version is out of date, please [create an issue or pull request](https://github.com/Microsoft/vcpkg) on the vcpkg repository.
--- ---

View File

@@ -222,6 +222,16 @@ available warnings
When set to ```yes``` Catch will report the duration of each test case, in milliseconds. Note that it does this regardless of whether a test case passes or fails. Note, also, the certain reporters (e.g. Junit) always report test case durations regardless of this option being set or not. When set to ```yes``` Catch will report the duration of each test case, in milliseconds. Note that it does this regardless of whether a test case passes or fails. Note, also, the certain reporters (e.g. Junit) always report test case durations regardless of this option being set or not.
<pre>-D, --min-duration &lt;value></pre>
> `--min-duration` was [introduced](https://github.com/catchorg/Catch2/pull/1910) in Catch 2.13.0
When set, Catch will report the duration of each test case that took more
than &lt;value> seconds, in milliseconds. This option is overriden by both
`-d yes` and `-d no`, so that either all durations are reported, or none
are.
<a id="input-file"></a> <a id="input-file"></a>
## Load test names to run from a file ## Load test names to run from a file
<pre>-f, --input-file &lt;filename></pre> <pre>-f, --input-file &lt;filename></pre>
@@ -243,15 +253,25 @@ This option lists all available tests in a non-indented form, one on each line.
Test cases are ordered one of three ways: Test cases are ordered one of three ways:
### decl ### decl
Declaration order (this is the default order if no --order argument is provided). The order the tests were originally declared in. Note that ordering between files is not guaranteed and is implementation dependent. Declaration order (this is the default order if no --order argument is provided).
Tests in the same TU are sorted using their declaration orders, different
TUs are in an implementation (linking) dependent order.
### lex ### lex
Lexicographically sorted. Tests are sorted, alpha-numerically, by name. Lexicographic order. Tests are sorted by their name, their tags are ignored.
### rand ### rand
Randomly sorted. Test names are sorted using ```std::random_shuffle()```. By default the random number generator is seeded with 0 - and so the order is repeatable. To control the random seed see <a href="#rng-seed">rng-seed</a>.
Randomly sorted. The order is dependent on Catch2's random seed (see
[`--rng-seed`](#rng-seed)), and is subset invariant. What this means
is that as long as the random seed is fixed, running only some tests
(e.g. via tag) does not change their relative order.
> The subset stability was introduced in Catch2 v2.12.0
<a id="rng-seed"></a> <a id="rng-seed"></a>
## Specify a seed for the Random Number Generator ## Specify a seed for the Random Number Generator

View File

@@ -1,100 +1,134 @@
<a id="top"></a> <a id="top"></a>
# Contributing to Catch # Contributing to Catch2
**Contents**<br> **Contents**<br>
[Branches](#branches)<br> [Using Git(Hub)](#using-github)<br>
[Directory structure](#directory-structure)<br>
[Testing your changes](#testing-your-changes)<br> [Testing your changes](#testing-your-changes)<br>
[Documenting your code](#documenting-your-code)<br> [Writing documentation](#writing-documentation)<br>
[Code constructs to watch out for](#code-constructs-to-watch-out-for)<br> [Writing code](#writing-code)<br>
[CoC](#coc)<br>
So you want to contribute something to Catch? That's great! Whether it's a bug fix, a new feature, support for So you want to contribute something to Catch2? That's great! Whether it's
additional compilers - or just a fix to the documentation - all contributions are very welcome and very much appreciated. a bug fix, a new feature, support for additional compilers - or just
Of course so are bug reports and other comments and questions. a fix to the documentation - all contributions are very welcome and very
much appreciated. Of course so are bug reports, other comments, and
questions, but generally it is a better idea to ask questions in our
[Discord](https://discord.gg/4CWS9zD), than in the issue tracker.
If you are contributing to the code base there are a few simple guidelines to keep in mind. This also includes notes to
help you find your way around. As this is liable to drift out of date please raise an issue or, better still, a pull
request for this file, if you notice that.
## Branches This page covers some guidelines and helpful tips for contributing
to the codebase itself.
Ongoing development is currently on _master_. At some point an integration branch will be set-up and PRs should target ## Using Git(Hub)
that - but for now it's all against master. You may see feature branches come and go from time to time, too.
## Directory structure Ongoing development happens in the `v2.x` branch for Catch2 v2, and in
`devel` for the next major version, v3.
_Users_ of Catch primarily use the single header version. _Maintainers_ should work with the full source (which is still, Commits should be small and atomic. A commit is atomic when, after it is
primarily, in headers). This can be found in the `include` folder. There are a set of test files, currently under applied, the codebase, tests and all, still works as expected. Small
`projects/SelfTest`. The test app can be built via CMake from the `CMakeLists.txt` file in the root, or you can generate commits are also preferred, as they make later operations with git history,
project files for Visual Studio, XCode, and others (instructions in the `projects` folder). If you have access to CLion, whether it is bisecting, reverting, or something else, easier.
it can work with the CMake file directly.
As well as the runtime test files you'll also see a `SurrogateCpps` directory under `projects/SelfTest`. _When submitting a pull request please do not include changes to the
This contains a set of .cpp files that each `#include` a single header. single include. This means do not include them in your git commits!_
While these files are not essential to compilation they help to keep the implementation headers self-contained.
At time of writing this set is not complete but has reasonable coverage.
If you add additional headers please try to remember to add a surrogate cpp for it.
The other directories are `scripts` which contains a set of python scripts to help in testing Catch as well as
generating the single include, and `docs`, which contains the documentation as a set of markdown files.
__When submitting a pull request please do not include changes to the single include, or to the version number file When addressing review comments in a MR, please do not rebase/squash the
as these are managed by the scripts!__ commits immediately. Doing so makes it harder to review the new changes,
slowing down the process of merging a MR. Instead, when addressing review
comments, you should append new commits to the branch and only squash
them into other commits when the MR is ready to be merged. We recommend
creating new commits with `git commit --fixup` (or `--squash`) and then
later squashing them with `git rebase --autosquash` to make things easier.
## Testing your changes ## Testing your changes
Obviously all changes to Catch's code should be tested. If you added new _Note: Running Catch2's tests requires Python3_
functionality, you should add tests covering and showcasing it. Even if you have
only made changes to Catch internals (i.e. you implemented some performance
improvements), you should still test your changes.
This means 2 things
* Compiling Catch's SelfTest project: Catch2 has multiple layers of tests that are then run as part of our CI.
The most obvious one are the unit tests compiled into the `SelfTest`
binary. These are then used in "Approval tests", which run (almost) all
tests from `SelfTest` through a specific reporter and then compare the
generated output with a known good output ("Baseline"). By default, new
tests should be placed here.
However, not all tests can be written as plain unit tests. For example,
checking that Catch2 orders tests randomly when asked to, and that this
random ordering is subset-invariant, is better done as an integration
test using an external check script. Catch2 integration tests are written
using CTest, either as a direct command invocation + pass/fail regex,
or by delegating the check to a Python script.
There are also two more kinds of tests, examples and "ExtraTests".
Examples serve as a compilation test on the single-header distribution,
and present a small and self-contained snippets of using Catch2 for
writing tests. ExtraTests then are tests that either take a long time
to run, or require separate compilation, e.g. because of testing compile
time configuration options, and take a long time because of that.
Both of these are compiled against the single-header distribution of
Catch2, and thus might require you to regenerate it manually. This is
done by calling the `generateSingleHeader.py` script in `scripts`.
Examples and ExtraTests are not compiled by default. To compile them,
add `-DCATCH_BUILD_EXAMPLES=ON` and `-DCATCH_BUILD_EXTRA_TESTS=ON` to
the invocation of CMake configuration step.
Bringing this all together, the steps below should configure, build,
and run all tests in the `Debug` compilation.
1. Regenerate the single header distribution
``` ```
$ cd Catch2 $ cd Catch2
$ cmake -Bdebug-build -H. -DCMAKE_BUILD_TYPE=Debug $ ./scripts/generateSingleHeader.py
```
2. Configure the full test build
```
$ cmake -Bdebug-build -H. -DCMAKE_BUILD_TYPE=Debug -DCATCH_BUILD_EXAMPLES=ON -DCATCH_BUILD_EXTRA_TESTS=ON
```
3. Run the actual build
```
$ cmake --build debug-build $ cmake --build debug-build
``` ```
because code that does not compile is evidently incorrect. Obviously, 4. Run the tests using CTest
you are not expected to have access to all the compilers and platforms
supported by Catch2, but you should at least smoke test your changes
on your platform. Our CI pipeline will check your PR against most of
the supported platforms, but it takes an hour to finish -- compiling
locally takes just a few minutes.
* Running the tests via CTest:
``` ```
$ cd debug-build $ cd debug-build
$ ctest -j 2 --output-on-failure $ ctest -j 4 --output-on-failure -C Debug
``` ```
__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
do not, it means that your changes weren't run as part of them. This
_might_ be intentional, but usually is not.
The approval tests compare current output of the SelfTest binary in various
configurations against known good outputs. The reason it fails is,
_usually_, that you've added new tests but have not yet approved the changes
they introduce. This is done with the `scripts/approve.py` script, but
before you do so, you need to check that the introduced changes are indeed
intentional.
## Documenting your code ## Writing documentation
If you have added new feature to Catch2, it needs documentation, so that If you have added new feature to Catch2, it needs documentation, so that
other people can use it as well. This section collects some technical other people can use it as well. This section collects some technical
information that you will need for updating Catch2's documentation, and information that you will need for updating Catch2's documentation, and
possibly some generic advise as well. possibly some generic advise as well.
### Technicalities
First, the technicalities: First, the technicalities:
* If you have introduced a new document, there is a simple template you
should use. It provides you with the top anchor mentioned to link to
(more below), and also with a backlink to the top of the documentation:
```markdown
<a id="top"></a>
# Cool feature
Text that explains how to use the cool feature.
---
[Home](Readme.md#top)
```
* Crosslinks to different pages should target the `top` anchor, like this
`[link to contributing](contributing.md#top)`.
* We introduced version tags to the documentation, which show users in * We introduced version tags to the documentation, which show users in
which version a specific feature was introduced. This means that newly which version a specific feature was introduced. This means that newly
written documentation should be tagged with a placeholder, that will written documentation should be tagged with a placeholder, that will
@@ -106,23 +140,8 @@ tags for other features).
placeholder is usually used after a section heading placeholder is usually used after a section heading
* `> X (Y and Z) was [introduced](link-to-issue-or-PR) in Catch X.Y.Z` * `> X (Y and Z) was [introduced](link-to-issue-or-PR) in Catch X.Y.Z`
- this placeholder is used when you need to tag a subpart of something, - this placeholder is used when you need to tag a subpart of something,
e.g. list e.g. a list
* Crosslinks to different pages should target the `top` anchor, like this
`[link to contributing](contributing.md#top)`.
* If you have introduced a new document, there is a simple template you
should use. It provides you with the top anchor mentioned above, and also
with a backlink to the top of the documentation:
```markdown
<a id="top"></a>
# Cool feature
Text that explains how to use the cool feature.
---
[Home](Readme.md#top)
```
* For pages with more than 4 subheadings, we provide a table of contents * For pages with more than 4 subheadings, we provide a table of contents
(ToC) at the top of the page. Because GitHub markdown does not support (ToC) at the top of the page. Because GitHub markdown does not support
automatic generation of ToC, it has to be handled semi-manually. Thus, automatic generation of ToC, it has to be handled semi-manually. Thus,
@@ -130,21 +149,54 @@ if you've added a new subheading to some page, you should add it to the
ToC. This can be done either manually, or by running the ToC. This can be done either manually, or by running the
`updateDocumentToC.py` script in the `scripts/` folder. `updateDocumentToC.py` script in the `scripts/` folder.
### Contents
Now, for the generic tips: Now, for some content tips:
* Usage examples are good
* Don't be afraid to introduce new pages * Usage examples are good. However, having large code snippets inline
* Try to be reasonably consistent with the surrounding documentation can make the documentation less readable, and so the inline snippets
should be kept reasonably short. To provide more complex compilable
examples, consider adding new .cpp file to `examples/`.
* Don't be afraid to introduce new pages. The current documentation
tends towards long pages, but a lot of that is caused by legacy, and
we know that some of the pages are overly big and unfocused.
* When adding information to an existing page, please try to keep your
formatting, style and changes consistent with the rest of the page.
* Any documentation has multiple different audiences, that desire
different information from the text. The 3 basic user-types to try and
cover are:
* A beginner to Catch2, who requires closer guidance for the usage of Catch2.
* Advanced user of Catch2, who want to customize their usage.
* Experts, looking for full reference of Catch2's capabilities.
## Writing code
If want to contribute code, this section contains some simple rules
and tips on things like code formatting, code constructions to avoid,
and so on.
## Code constructs to watch out for ### Formatting
To make code formatting simpler for the contributors, Catch2 provides
its own config for `clang-format`. However, because it is currently
impossible to replicate existing Catch2's formatting in clang-format,
using it to reformat a whole file would cause massive diffs. To keep
the size of your diffs reasonable, you should only use clang-format
on the newly changed code.
### Code constructs to watch out for
This section is a (sadly incomplete) listing of various constructs that This section is a (sadly incomplete) listing of various constructs that
are problematic and are not always caught by our CI infrastructure. are problematic and are not always caught by our CI infrastructure.
### Naked exceptions and exceptions-related function
#### Naked exceptions and exceptions-related function
If you are throwing an exception, it should be done via `CATCH_ERROR` If you are throwing an exception, it should be done via `CATCH_ERROR`
or `CATCH_RUNTIME_ERROR` in `catch_enforce.h`. These macros will handle or `CATCH_RUNTIME_ERROR` in `catch_enforce.h`. These macros will handle
@@ -155,7 +207,8 @@ CI, but luckily there should not be too many reasons to use these.
However, if you do, they should be kept behind a However, if you do, they should be kept behind a
`CATCH_CONFIG_DISABLE_EXCEPTIONS` macro. `CATCH_CONFIG_DISABLE_EXCEPTIONS` macro.
### Unqualified usage of functions from C's stdlib
#### Unqualified usage of functions from C's stdlib
If you are using a function from C's stdlib, please include the header If you are using a function from C's stdlib, please include the header
as `<cfoo>` and call the function qualified. The common knowledge that as `<cfoo>` and call the function qualified. The common knowledge that
@@ -163,7 +216,12 @@ there is no difference is wrong, QNX and VxWorks won't compile if you
include the header as `<cfoo>` and call the function unqualified. include the header as `<cfoo>` and call the function unqualified.
---- ## CoC
This project has a [CoC](../CODE_OF_CONDUCT.md). Please adhere to it
while contributing to Catch2.
-----------
_This documentation will always be in-progress as new information comes _This documentation will always be in-progress as new information comes
up, but we are trying to keep it as up to date as possible._ up, but we are trying to keep it as up to date as possible._

View File

@@ -72,6 +72,13 @@ Instead you will have to write this:
REQUIRE_THAT(foo(), m1 || m2 || m3); REQUIRE_THAT(foo(), m1 || m2 || m3);
``` ```
### `ParseAndAddCatchTests.cmake`
The CMake/CTest integration using `ParseAndAddCatchTests.cmake` is deprecated,
as it can be replaced by `Catch.cmake` that provides the function
`catch_discover_tests` to get tests directly from a CMake target via the
command line interface instead of parsing C++ code with regular expressions.
## Planned changes ## Planned changes

View File

@@ -12,23 +12,88 @@ are run once per each value in a generator.
This is best explained with an example: This is best explained with an example:
```cpp ```cpp
TEST_CASE("Generators") { TEST_CASE("Generators") {
auto i = GENERATE(1, 2, 3); auto i = GENERATE(1, 3, 5);
SECTION("one") { REQUIRE(is_odd(i));
auto j = GENERATE( -3, -2, -1 );
REQUIRE(j < i);
}
} }
``` ```
The assertion in this test case will be run 9 times, because there The "Generators" `TEST_CASE` will be entered 3 times, and the value of
are 3 possible values for `i` (1, 2, and 3) and there are 3 possible `i` will be 1, 3, and 5 in turn. `GENERATE`s can also be used multiple
values for `j` (-3, -2, and -1). times at the same scope, in which case the result will be a cartesian
product of all elements in the generators. This means that in the snippet
below, the test case will be run 6 (2\*3) times.
```cpp
TEST_CASE("Generators") {
auto i = GENERATE(1, 2);
auto j = GENERATE(3, 4, 5);
}
```
There are 2 parts to generators in Catch2, the `GENERATE` macro together There are 2 parts to generators in Catch2, the `GENERATE` macro together
with the already provided generators, and the `IGenerator<T>` interface with the already provided generators, and the `IGenerator<T>` interface
that allows users to implement their own generators. that allows users to implement their own generators.
## Combining `GENERATE` and `SECTION`.
`GENERATE` can be seen as an implicit `SECTION`, that goes from the place
`GENERATE` is used, to the end of the scope. This can be used for various
effects. The simplest usage is shown below, where the `SECTION` "one"
runs 4 (2\*2) times, and `SECTION` "two" is run 6 times (2\*3).
```cpp
TEST_CASE("Generators") {
auto i = GENERATE(1, 2);
SECTION("one") {
auto j = GENERATE(-3, -2);
REQUIRE(j < i);
}
SECTION("two") {
auto k = GENERATE(4, 5, 6);
REQUIRE(i != k);
}
}
```
The specific order of the `SECTION`s will be "one", "one", "two", "two",
"two", "one"...
The fact that `GENERATE` introduces a virtual `SECTION` can also be used
to make a generator replay only some `SECTION`s, without having to
explicitly add a `SECTION`. As an example, the code below reports 3
assertions, because the "first" section is run once, but the "second"
section is run twice.
```cpp
TEST_CASE("GENERATE between SECTIONs") {
SECTION("first") { REQUIRE(true); }
auto _ = GENERATE(1, 2);
SECTION("second") { REQUIRE(true); }
}
```
This can lead to surprisingly complex test flows. As an example, the test
below will report 14 assertions:
```cpp
TEST_CASE("Complex mix of sections and generates") {
auto i = GENERATE(1, 2);
SECTION("A") {
SUCCEED("A");
}
auto j = GENERATE(3, 4);
SECTION("B") {
SUCCEED("B");
}
auto k = GENERATE(5, 6);
SUCCEED();
}
```
> The ability to place `GENERATE` between two `SECTION`s was [introduced](https://github.com/catchorg/Catch2/issues/1938) in Catch 2.13.0.
## Provided generators ## Provided generators
Catch2's provided generator functionality consists of three parts, Catch2's provided generator functionality consists of three parts,

View File

@@ -104,6 +104,20 @@ Both of these solutions have their problems, but should let you wring parallelis
## 3rd party bugs ## 3rd party bugs
This section outlines known bugs in 3rd party components (this means compilers, standard libraries, standard runtimes). This section outlines known bugs in 3rd party components (this means compilers, standard libraries, standard runtimes).
### Visual Studio 2015 -- `GENERATE` does not compile if it would deduce char array
VS 2015 refuses to compile `GENERATE` statements that would deduce to a
char array with known size, e.g. this:
```cpp
TEST_CASE("Deducing string lit") {
auto param = GENERATE("start", "stop");
}
```
A workaround for this is to use the `as` helper and force deduction of
either a `char const*` or a `std::string`.
### Visual Studio 2017 -- raw string literal in assert fails to compile ### Visual Studio 2017 -- raw string literal in assert fails to compile
There is a known bug in Visual Studio 2017 (VC 15), that causes compilation error when preprocessor attempts to stringize a raw string literal (`#` preprocessor is applied to it). This snippet is sufficient to trigger the compilation error: There is a known bug in Visual Studio 2017 (VC 15), that causes compilation error when preprocessor attempts to stringize a raw string literal (`#` preprocessor is applied to it). This snippet is sufficient to trigger the compilation error:
```cpp ```cpp

View File

@@ -16,6 +16,7 @@
- Configuration: [Provide your own output streams](../examples/231-Cfg-OutputStreams.cpp) - Configuration: [Provide your own output streams](../examples/231-Cfg-OutputStreams.cpp)
- Generators: [Create your own generator](../examples/300-Gen-OwnGenerator.cpp) - Generators: [Create your own generator](../examples/300-Gen-OwnGenerator.cpp)
- Generators: [Use map to convert types in GENERATE expression](../examples/301-Gen-MapTypeConversion.cpp) - Generators: [Use map to convert types in GENERATE expression](../examples/301-Gen-MapTypeConversion.cpp)
- Generators: [Run test with a table of input values](../examples/302-Gen-Table.cpp)
- Generators: [Use variables in generator expressions](../examples/310-Gen-VariablesInGenerators.cpp) - Generators: [Use variables in generator expressions](../examples/310-Gen-VariablesInGenerators.cpp)
- Generators: [Use custom variable capture in generator expressions](../examples/311-Gen-CustomCapture.cpp) - Generators: [Use custom variable capture in generator expressions](../examples/311-Gen-CustomCapture.cpp)

View File

@@ -20,18 +20,21 @@ Listing a project here does not imply endorsement and the plan is to keep these
### [ApprovalTests.cpp](https://github.com/approvals/ApprovalTests.cpp) ### [ApprovalTests.cpp](https://github.com/approvals/ApprovalTests.cpp)
C++11 implementation of Approval Tests, for quick, convenient testing of legacy code. C++11 implementation of Approval Tests, for quick, convenient testing of legacy code.
### [args](https://github.com/Taywee/args)
A simple header-only C++ argument parser library.
### [Azmq](https://github.com/zeromq/azmq) ### [Azmq](https://github.com/zeromq/azmq)
Boost Asio style bindings for ZeroMQ. Boost Asio style bindings for ZeroMQ.
### [Cataclysm: Dark Days Ahead](https://github.com/CleverRaven/Cataclysm-DDA) ### [Cataclysm: Dark Days Ahead](https://github.com/CleverRaven/Cataclysm-DDA)
Post-apocalyptic survival RPG. Post-apocalyptic survival RPG.
### [ChakraCore](https://github.com/Microsoft/ChakraCore)
The core part of the Chakra JavaScript engine that powers Microsoft Edge.
### [ChaiScript](https://github.com/ChaiScript/ChaiScript) ### [ChaiScript](https://github.com/ChaiScript/ChaiScript)
A, header-only, embedded scripting language designed from the ground up to directly target C++ and take advantage of modern C++ development techniques. A, header-only, embedded scripting language designed from the ground up to directly target C++ and take advantage of modern C++ development techniques.
### [ChakraCore](https://github.com/Microsoft/ChakraCore)
The core part of the Chakra JavaScript engine that powers Microsoft Edge.
### [Clara](https://github.com/philsquared/Clara) ### [Clara](https://github.com/philsquared/Clara)
A, single-header-only, type-safe, command line parser - which also prints formatted usage strings. A, single-header-only, type-safe, command line parser - which also prints formatted usage strings.
@@ -65,9 +68,6 @@ A small C++ library wrapper for the native C ODBC API.
### [Nonius](https://github.com/libnonius/nonius) ### [Nonius](https://github.com/libnonius/nonius)
A header-only framework for benchmarking small snippets of C++ code. A header-only framework for benchmarking small snippets of C++ code.
### [SOCI](https://github.com/SOCI/soci)
The C++ Database Access Library.
### [polymorphic_value](https://github.com/jbcoe/polymorphic_value) ### [polymorphic_value](https://github.com/jbcoe/polymorphic_value)
A polymorphic value-type for C++. A polymorphic value-type for C++.
@@ -77,20 +77,26 @@ A C++ client library for Consul. Consul is a distributed tool for discovering an
### [Reactive-Extensions/ RxCpp](https://github.com/Reactive-Extensions/RxCpp) ### [Reactive-Extensions/ RxCpp](https://github.com/Reactive-Extensions/RxCpp)
A library of algorithms for values-distributed-in-time. A library of algorithms for values-distributed-in-time.
### [thor](https://github.com/xorz57/thor) ### [SOCI](https://github.com/SOCI/soci)
Wrapper Library for CUDA. The C++ Database Access Library.
### [TextFlowCpp](https://github.com/philsquared/textflowcpp) ### [TextFlowCpp](https://github.com/philsquared/textflowcpp)
A small, single-header-only, library for wrapping and composing columns of text. A small, single-header-only, library for wrapping and composing columns of text.
### [thor](https://github.com/xorz57/thor)
Wrapper Library for CUDA.
### [toml++](https://github.com/marzer/tomlplusplus)
A header-only TOML parser and serializer for modern C++.
### [Trompeloeil](https://github.com/rollbear/trompeloeil) ### [Trompeloeil](https://github.com/rollbear/trompeloeil)
A thread-safe header-only mocking framework for C++14. A thread-safe header-only mocking framework for C++14.
### [args](https://github.com/Taywee/args)
A simple header-only C++ argument parser library.
## Applications & Tools ## Applications & Tools
### [App Mesh](https://github.com/laoshanxi/app-mesh)
A high available cloud native micro-service application management platform implemented by modern C++.
### [ArangoDB](https://github.com/arangodb/arangodb) ### [ArangoDB](https://github.com/arangodb/arangodb)
ArangoDB is a native multi-model database with flexible data models for documents, graphs, and key-values. ArangoDB is a native multi-model database with flexible data models for documents, graphs, and key-values.
@@ -103,6 +109,9 @@ MAME originally stood for Multiple Arcade Machine Emulator.
### [Newsbeuter](https://github.com/akrennmair/newsbeuter) ### [Newsbeuter](https://github.com/akrennmair/newsbeuter)
Newsbeuter is an open-source RSS/Atom feed reader for text terminals. Newsbeuter is an open-source RSS/Atom feed reader for text terminals.
### [PopHead](https://github.com/SPC-Some-Polish-Coders/PopHead)
A 2D, Zombie, RPG game which is being made on our own engine.
### [raspigcd](https://github.com/pantadeusz/raspigcd) ### [raspigcd](https://github.com/pantadeusz/raspigcd)
Low level CLI app and library for execution of GCODE on Raspberry Pi without any additional microcontrolers (just RPi + Stepsticks). Low level CLI app and library for execution of GCODE on Raspberry Pi without any additional microcontrolers (just RPi + Stepsticks).
@@ -112,9 +121,6 @@ SpECTRE is a code for multi-scale, multi-physics problems in astrophysics and gr
### [Standardese](https://github.com/foonathan/standardese) ### [Standardese](https://github.com/foonathan/standardese)
Standardese aims to be a nextgen Doxygen. Standardese aims to be a nextgen Doxygen.
### [PopHead](https://github.com/SPC-Some-Polish-Coders/PopHead)
A 2D, Zombie, RPG game which is being made on our own engine.
--- ---
[Home](Readme.md#top) [Home](Readme.md#top)

View File

@@ -121,7 +121,7 @@ constructor, or before Catch2's session is created in user's own main._
`ANON_TEST_CASE` is a `TEST_CASE` replacement that will autogenerate `ANON_TEST_CASE` is a `TEST_CASE` replacement that will autogenerate
unique name. The advantage of this is that you do not have to think unique name. The advantage of this is that you do not have to think
of a name for the test case,`the disadvantage is that the name doesn't of a name for the test case, the disadvantage is that the name doesn't
necessarily remain stable across different links, and thus it might be necessarily remain stable across different links, and thus it might be
hard to run directly. hard to run directly.

View File

@@ -11,9 +11,9 @@ The easiest way to use Catch is to let it supply ```main()``` for you and handle
This is achieved by writing ```#define CATCH_CONFIG_MAIN``` before the ```#include "catch.hpp"``` in *exactly one* source file. This is achieved by writing ```#define CATCH_CONFIG_MAIN``` before the ```#include "catch.hpp"``` in *exactly one* source file.
Sometimes, though, you need to write your own version of main(). You can do this by writing ```#define CATCH_CONFIG_RUNNER``` instead. Now you are free to write ```main()``` as normal and call into Catch yourself manually. Sometimes, though, you need to write your own version of main(). You can do this by writing ```#define CATCH_CONFIG_RUNNER``` instead. Now you are free to write ```main()``` as normal and call into Catch yourself manually. You now have a lot of flexibility - but here are three recipes to get your started:
You now have a lot of flexibility - but here are three recipes to get your started: **Important note: you can only provide `main` in the same file you defined `CATCH_CONFIG_RUNNER`.**
## Let Catch take full control of args and config ## Let Catch take full control of args and config

View File

@@ -2,6 +2,20 @@
# Release notes # Release notes
**Contents**<br> **Contents**<br>
[2.13.8](#2138)<br>
[2.13.7](#2137)<br>
[2.13.6](#2136)<br>
[2.13.5](#2135)<br>
[2.13.4](#2134)<br>
[2.13.3](#2133)<br>
[2.13.2](#2132)<br>
[2.13.1](#2131)<br>
[2.13.0](#2130)<br>
[2.12.4](#2124)<br>
[2.12.3](#2123)<br>
[2.12.2](#2122)<br>
[2.12.1](#2121)<br>
[2.12.0](#2120)<br>
[2.11.3](#2113)<br> [2.11.3](#2113)<br>
[2.11.2](#2112)<br> [2.11.2](#2112)<br>
[2.11.1](#2111)<br> [2.11.1](#2111)<br>
@@ -34,6 +48,200 @@
[Older versions](#older-versions)<br> [Older versions](#older-versions)<br>
[Even Older versions](#even-older-versions)<br> [Even Older versions](#even-older-versions)<br>
## 2.13.8
### Fixes
* Made `Approx::operator()` const (#2288)
* Improved pkg-config files (#2284)
* Fixed warning suppression leaking out of Catch2 when compiled with clang.exe (#2280)
* The macro-generated names for things like `TEST_CASE` no longer create reserved identifiers (#2336)
### Improvements
* Clang-tidy should no longer warn about missing virtual dispatch in `FilterGenerator`'s constructor (#2314)
## 2.13.7
### Fixes
* Added missing `<iterator>` include in benchmarking. (#2231)
* Fixed noexcept build with benchmarking enabled (#2235)
* Fixed build for compilers with C++17 support but without C++17 library support (#2195)
* JUnit only uses 3 decimal places when reporting durations (#2221)
* `!mayfail` tagged tests are now marked as `skipped` in JUnit reporter output (#2116)
## 2.13.6
### Fixes
* Disabling all signal handlers no longer breaks compilation (#2212, #2213)
### Miscellaneous
* `catch_discover_tests` should handle escaped semicolon (`;`) better (#2214, #2215)
## 2.13.5
### Improvements
* Detection of MAC and IPHONE platforms has been improved (#2140, #2157)
* Added workaround for bug in XLC 16.1.0.1 (#2155)
* Add detection for LCC when it is masquerading as GCC (#2199)
* Modified posix signal handling so it supports newer libcs (#2178)
* `MINSIGSTKSZ` was no longer usable in constexpr context.
### Fixes
* Fixed compilation of benchmarking when `min` and `max` macros are defined (#2159)
* Including `windows.h` without `NOMINMAX` remains a really bad idea, don't do it
### Miscellaneous
* `Catch2WithMain` target (static library) is no longer built by default (#2142)
* Building it by default was at best unnecessary overhead for people not using it, and at worst it caused trouble with install paths
* To have it built, set CMake option `CATCH_BUILD_STATIC_LIBRARY` to `ON`
* The check whether Catch2 is being built as a subproject is now more reliable (#2202, #2204)
* The problem was that if the variable name used internally was defined the project including Catch2 as subproject, it would not be properly overwritten for Catch2's CMake.
## 2.13.4
### Improvements
* Improved the hashing algorithm used for shuffling test cases (#2070)
* `TEST_CASE`s that differ only in the last character should be properly shuffled
* Note that this means that v2.13.4 gives you a different order of test cases than 2.13.3, even given the same seed.
### Miscellaneous
* Deprecated `ParseAndAddCatchTests` CMake integration (#2092)
* It is impossible to implement it properly for all the different test case variants Catch2 provides, and there are better options provided.
* Use `catch_discover_tests` instead, which uses runtime information about available tests.
* Fixed bug in `catch_discover_tests` that would cause it to fail when used in specific project structures (#2119)
* Added Bazel build file
* Added an experimental static library target to CMake
## 2.13.3
### Fixes
* Fixed possible infinite loop when combining generators with section filter (`-c` option) (#2025)
### Miscellaneous
* Fixed `ParseAndAddCatchTests` not finding `TEST_CASE`s without tags (#2055, #2056)
* `ParseAndAddCatchTests` supports `CMP0110` policy for changing behaviour of `add_test` (#2057)
* This was the shortlived change in CMake 3.18.0 that temporarily broke `ParseAndAddCatchTests`
## 2.13.2
### Improvements
* Implemented workaround for AppleClang shadowing bug (#2030)
* Implemented workaround for NVCC ICE (#2005, #2027)
### Fixes
* Fixed detection of `std::uncaught_exceptions` support under non-msvc platforms (#2021)
* Fixed the experimental stdout/stderr capture under Windows (#2013)
### Miscellaneous
* `catch_discover_tests` has been improved significantly (#2023, #2039)
* You can now specify which reporter should be used
* You can now modify where the output will be written
* `WORKING_DIRECTORY` setting is respected
* `ParseAndAddCatchTests` now supports `TEMPLATE_TEST_CASE` macros (#2031)
* Various documentation fixes and improvements (#2022, #2028, #2034)
## 2.13.1
### Improvements
* `ParseAndAddCatchTests` handles CMake v3.18.0 correctly (#1984)
* Improved autodetection of `std::byte` (#1992)
* Simplified implementation of templated test cases (#2007)
* This should have a tiny positive effect on its compilation throughput
### Fixes
* Automatic stringification of ranges handles sentinel ranges properly (#2004)
## 2.13.0
### Improvements
* `GENERATE` can now follow a `SECTION` at the same level of nesting (#1938)
* The `SECTION`(s) before the `GENERATE` will not be run multiple times, the following ones will.
* Added `-D`/`--min-duration` command line flag (#1910)
* If a test takes longer to finish than the provided value, its name and duration will be printed.
* This flag is overriden by setting `-d`/`--duration`.
### Fixes
* `TAPReporter` no longer skips successful assertions (#1983)
## 2.12.4
### Improvements
* Added support for MacOS on ARM (#1971)
## 2.12.3
### Fixes
* `GENERATE` nested in a for loop no longer creates multiple generators (#1913)
* Fixed copy paste error breaking `TEMPLATE_TEST_CASE_SIG` for 6 or more arguments (#1954)
* Fixed potential UB when handling non-ASCII characters in CLI args (#1943)
### Improvements
* There can be multiple calls to `GENERATE` on a single line
* Improved `fno-except` support for platforms that do not provide shims for exception-related std functions (#1950)
* E.g. the Green Hills C++ compiler
* XmlReporter now also reports test-case-level statistics (#1958)
* This is done via a new element, `OverallResultsCases`
### Miscellaneous
* Added `.clang-format` file to the repo (#1182, #1920)
* Rewrote contributing docs
* They should explain the different levels of testing and so on much better
## 2.12.2
### Fixes
* Fixed compilation failure if `is_range` ADL found deleted function (#1929)
* Fixed potential UB in `CAPTURE` if the expression contained non-ASCII characters (#1925)
### Improvements
* `std::result_of` is not used if `std::invoke_result` is available (#1934)
* JUnit reporter writes out `status` attribute for tests (#1899)
* Suppresed clang-tidy's `hicpp-vararg` warning (#1921)
* Catch2 was already suppressing the `cppcoreguidelines-pro-type-vararg` alias of the warning
## 2.12.1
### Fixes
* Vector matchers now support initializer list literals better
### Improvements
* Added support for `^` (bitwise xor) to `CHECK` and `REQUIRE`
## 2.12.0
### Improvements
* Running tests in random order (`--order rand`) has been reworked significantly (#1908)
* Given same seed, all platforms now produce the same order
* Given same seed, the relative order of tests does not change if you select only a subset of them
* Vector matchers support custom allocators (#1909)
* `|` and `&` (bitwise or and bitwise and) are now supported in `CHECK` and `REQUIRE`
* The resulting type must be convertible to `bool`
### Fixes
* Fixed computation of benchmarking column widths in ConsoleReporter (#1885, #1886)
* Suppressed clang-tidy's `cppcoreguidelines-pro-type-vararg` in assertions (#1901)
* It was a false positive trigered by the new warning support workaround
* Fixed bug in test specification parser handling of OR'd patterns using escaping (#1905)
### Miscellaneous
* Worked around IBM XL's codegen bug (#1907)
* It would emit code for _destructors_ of temporaries in an unevaluated context
* Improved detection of stdlib's support for `std::uncaught_exceptions` (#1911)
## 2.11.3 ## 2.11.3
### Fixes ### Fixes
@@ -543,7 +751,7 @@ than `single_include/catch.hpp`.**
* CLR objects (`T^`) can now be stringified (#1216) * CLR objects (`T^`) can now be stringified (#1216)
* This affects code compiled as C++/CLI * This affects code compiled as C++/CLI
* Added `PredicateMatcher`, a matcher that takes an arbitrary predicate function (#1236) * Added `PredicateMatcher`, a matcher that takes an arbitrary predicate function (#1236)
* See [documentation for details](https://github.com/catchorg/Catch2/blob/master/docs/matchers.md) * See [documentation for details](https://github.com/catchorg/Catch2/blob/v2.x/docs/matchers.md)
### Others ### Others
* Modified CMake-installed pkg-config to allow `#include <catch.hpp>`(#1239) * Modified CMake-installed pkg-config to allow `#include <catch.hpp>`(#1239)
@@ -571,7 +779,7 @@ than `single_include/catch.hpp`.**
* Added an option to warn (+ exit with error) when no tests were ran (#1158) * Added an option to warn (+ exit with error) when no tests were ran (#1158)
* Use as `-w NoTests` * Use as `-w NoTests`
* Added provisional support for Emscripten (#1114) * Added provisional support for Emscripten (#1114)
* [Added a way to override the fallback stringifier](https://github.com/catchorg/Catch2/blob/master/docs/configuration.md#fallback-stringifier) (#1024) * [Added a way to override the fallback stringifier](https://github.com/catchorg/Catch2/blob/v2.x/docs/configuration.md#fallback-stringifier) (#1024)
* This allows project's own stringification machinery to be easily reused for Catch * This allows project's own stringification machinery to be easily reused for Catch
* `Catch::Session::run()` now accepts `char const * const *`, allowing it to accept array of string literals (#1031, #1178) * `Catch::Session::run()` now accepts `char const * const *`, allowing it to accept array of string literals (#1031, #1178)
* The embedded version of Clara was bumped to v1.1.3 * The embedded version of Clara was bumped to v1.1.3

View File

@@ -5,6 +5,7 @@
[Short answer](#short-answer)<br> [Short answer](#short-answer)<br>
[Long answer](#long-answer)<br> [Long answer](#long-answer)<br>
[Practical example](#practical-example)<br> [Practical example](#practical-example)<br>
[Using the static library Catch2WithMain](#using-the-static-library-catch2withmain)<br>
[Other possible solutions](#other-possible-solutions)<br> [Other possible solutions](#other-possible-solutions)<br>
Several people have reported that test code written with Catch takes much longer to compile than they would expect. Why is that? Several people have reported that test code written with Catch takes much longer to compile than they would expect. Why is that?
@@ -64,6 +65,39 @@ tests-factorial.cpp:11: failed: Factorial(0) == 1 for: 0 == 1
Failed 1 test case, failed 1 assertion. Failed 1 test case, failed 1 assertion.
``` ```
## Using the static library Catch2WithMain
Catch2 also provides a static library that implements the runner. Note
that this support is experimental, due to interactions between Catch2 v2
implementation and C++ linking limitations.
As with the `Catch2` target, the `Catch2WithMain` CMake target can be used
either from a subdirectory, or from installed build.
### CMake
```cmake
add_executable(tests-factorial tests-factorial.cpp)
target_link_libraries(tests-factorial Catch2::Catch2WithMain)
```
### bazel
```python
cc_test(
name = "hello_world_test",
srcs = [
"test/hello_world_test.cpp",
],
deps = [
"lib_hello_world",
"@catch2//:catch2_with_main",
],
)
```
## Other possible solutions ## Other possible solutions
You can also opt to sacrifice some features in order to speed-up Catch's compilation times. For details see the [documentation on Catch's compile-time configuration](configuration.md#other-toggles). You can also opt to sacrifice some features in order to speed-up Catch's compilation times. For details see the [documentation on Catch's compile-time configuration](configuration.md#other-toggles).

View File

@@ -13,7 +13,7 @@
## Getting Catch2 ## Getting Catch2
The simplest way to get Catch2 is to download the latest [single header version](https://raw.githubusercontent.com/catchorg/Catch2/master/single_include/catch2/catch.hpp). The single header is generated by merging a set of individual headers but it is still just normal source code in a header file. The simplest way to get Catch2 is to download the latest [single header version](https://raw.githubusercontent.com/catchorg/Catch2/v2.x/single_include/catch2/catch.hpp). The single header is generated by merging a set of individual headers but it is still just normal source code in a header file.
Alternative ways of getting Catch2 include using your system package Alternative ways of getting Catch2 include using your system package
manager, or installing it using [its CMake package](cmake-integration.md#installing-catch2-from-git-repository). manager, or installing it using [its CMake package](cmake-integration.md#installing-catch2-from-git-repository).

View File

@@ -1,7 +1,9 @@
// 301-Gen-MapTypeConversion.cpp // 301-Gen-MapTypeConversion.cpp
// Shows how to use map to modify generator's return type. // Shows how to use map to modify generator's return type.
// TODO // Specifically we wrap a std::string returning generator with a generator
// that converts the strings using stoi, so the returned type is actually
// an int.
#include <catch2/catch.hpp> #include <catch2/catch.hpp>

View File

@@ -0,0 +1,54 @@
// 302-Gen-Table.cpp
// Shows how to use table to run a test many times with different inputs. Lifted from examples on
// issue #850.
#include <catch2/catch.hpp>
#include <string>
struct TestSubject {
// this is the method we are going to test. It returns the length of the
// input string.
size_t GetLength( const std::string& input ) const { return input.size(); }
};
TEST_CASE("Table allows pre-computed test inputs and outputs", "[example][generator]") {
using std::make_tuple;
// do setup here as normal
TestSubject subj;
SECTION("This section is run for each row in the table") {
std::string test_input;
size_t expected_output;
std::tie( test_input, expected_output ) =
GENERATE( table<std::string, size_t>(
{ /* In this case one of the parameters to our test case is the
* expected output, but this is not required. There could be
* multiple expected values in the table, which can have any
* (fixed) number of columns.
*/
make_tuple( "one", 3 ),
make_tuple( "two", 3 ),
make_tuple( "three", 5 ),
make_tuple( "four", 4 ) } ) );
// run the test
auto result = subj.GetLength(test_input);
// capture the input data to go with the outputs.
CAPTURE(test_input);
// check it matches the pre-calculated data
REQUIRE(result == expected_output);
} // end section
}
/* Possible simplifications where less legacy toolchain support is needed:
*
* - With libstdc++6 or newer, the make_tuple() calls can be omitted
* (technically C++17 but does not require -std in GCC/Clang). See
* https://stackoverflow.com/questions/12436586/tuple-vector-and-initializer-list
*
* - In C++17 mode std::tie() and the preceeding variable delcarations can be
* replaced by structured bindings: auto [test_input, expected] = GENERATE(
* table<std::string, size_t>({ ...
*/
// Compiling and running this file will result in 4 successful assertions

View File

@@ -23,11 +23,11 @@ TEST_CASE("Generate random doubles across different ranges",
})); }));
auto r2(r1); auto r2(r1);
// This will take r1 by reference and r2 by value. // This will take r1 by reference and r2 by value.
// Note that there are no advantages for doing so in this example, // Note that there are no advantages for doing so in this example,
// it is done only for expository purposes. // it is done only for expository purposes.
auto number = Catch::Generators::generate( CATCH_INTERNAL_LINEINFO, auto number = Catch::Generators::generate( "custom capture generator", CATCH_INTERNAL_LINEINFO,
[&r1, r2]{ [&r1, r2]{
using namespace Catch::Generators; using namespace Catch::Generators;
return makeGenerators(take(50, random(std::get<0>(r1), std::get<1>(r2)))); return makeGenerators(take(50, random(std::get<0>(r1), std::get<1>(r2))));

View File

@@ -46,6 +46,7 @@ set( SOURCES_IDIOMATIC_TESTS
210-Evt-EventListeners.cpp 210-Evt-EventListeners.cpp
300-Gen-OwnGenerator.cpp 300-Gen-OwnGenerator.cpp
301-Gen-MapTypeConversion.cpp 301-Gen-MapTypeConversion.cpp
302-Gen-Table.cpp
310-Gen-VariablesInGenerators.cpp 310-Gen-VariablesInGenerators.cpp
311-Gen-CustomCapture.cpp 311-Gen-CustomCapture.cpp
) )

View File

@@ -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 11 #define CATCH_VERSION_MINOR 13
#define CATCH_VERSION_PATCH 3 #define CATCH_VERSION_PATCH 8
#ifdef __clang__ #ifdef __clang__
# pragma clang system_header # pragma clang system_header
@@ -195,9 +195,9 @@
#if defined(CATCH_CONFIG_ENABLE_BENCHMARKING) #if defined(CATCH_CONFIG_ENABLE_BENCHMARKING)
#define CATCH_BENCHMARK(...) \ #define CATCH_BENCHMARK(...) \
INTERNAL_CATCH_BENCHMARK(INTERNAL_CATCH_UNIQUE_NAME(____C_A_T_C_H____B_E_N_C_H____), INTERNAL_CATCH_GET_1_ARG(__VA_ARGS__,,), INTERNAL_CATCH_GET_2_ARG(__VA_ARGS__,,)) INTERNAL_CATCH_BENCHMARK(INTERNAL_CATCH_UNIQUE_NAME(C_A_T_C_H_B_E_N_C_H_), INTERNAL_CATCH_GET_1_ARG(__VA_ARGS__,,), INTERNAL_CATCH_GET_2_ARG(__VA_ARGS__,,))
#define CATCH_BENCHMARK_ADVANCED(name) \ #define CATCH_BENCHMARK_ADVANCED(name) \
INTERNAL_CATCH_BENCHMARK_ADVANCED(INTERNAL_CATCH_UNIQUE_NAME(____C_A_T_C_H____B_E_N_C_H____), name) INTERNAL_CATCH_BENCHMARK_ADVANCED(INTERNAL_CATCH_UNIQUE_NAME(C_A_T_C_H_B_E_N_C_H_), name)
#endif // CATCH_CONFIG_ENABLE_BENCHMARKING #endif // CATCH_CONFIG_ENABLE_BENCHMARKING
// If CATCH_CONFIG_PREFIX_ALL is not defined then the CATCH_ prefix is not required // If CATCH_CONFIG_PREFIX_ALL is not defined then the CATCH_ prefix is not required
@@ -301,9 +301,9 @@
#if defined(CATCH_CONFIG_ENABLE_BENCHMARKING) #if defined(CATCH_CONFIG_ENABLE_BENCHMARKING)
#define BENCHMARK(...) \ #define BENCHMARK(...) \
INTERNAL_CATCH_BENCHMARK(INTERNAL_CATCH_UNIQUE_NAME(____C_A_T_C_H____B_E_N_C_H____), INTERNAL_CATCH_GET_1_ARG(__VA_ARGS__,,), INTERNAL_CATCH_GET_2_ARG(__VA_ARGS__,,)) INTERNAL_CATCH_BENCHMARK(INTERNAL_CATCH_UNIQUE_NAME(C_A_T_C_H_B_E_N_C_H_), INTERNAL_CATCH_GET_1_ARG(__VA_ARGS__,,), INTERNAL_CATCH_GET_2_ARG(__VA_ARGS__,,))
#define BENCHMARK_ADVANCED(name) \ #define BENCHMARK_ADVANCED(name) \
INTERNAL_CATCH_BENCHMARK_ADVANCED(INTERNAL_CATCH_UNIQUE_NAME(____C_A_T_C_H____B_E_N_C_H____), name) INTERNAL_CATCH_BENCHMARK_ADVANCED(INTERNAL_CATCH_UNIQUE_NAME(C_A_T_C_H_B_E_N_C_H_), name)
#endif // CATCH_CONFIG_ENABLE_BENCHMARKING #endif // CATCH_CONFIG_ENABLE_BENCHMARKING
using Catch::Detail::Approx; using Catch::Detail::Approx;
@@ -350,8 +350,8 @@ using Catch::Detail::Approx;
#define CATCH_WARN( msg ) (void)(0) #define CATCH_WARN( msg ) (void)(0)
#define CATCH_CAPTURE( msg ) (void)(0) #define CATCH_CAPTURE( msg ) (void)(0)
#define CATCH_TEST_CASE( ... ) INTERNAL_CATCH_TESTCASE_NO_REGISTRATION(INTERNAL_CATCH_UNIQUE_NAME( ____C_A_T_C_H____T_E_S_T____ )) #define CATCH_TEST_CASE( ... ) INTERNAL_CATCH_TESTCASE_NO_REGISTRATION(INTERNAL_CATCH_UNIQUE_NAME( C_A_T_C_H_T_E_S_T_ ))
#define CATCH_TEST_CASE_METHOD( className, ... ) INTERNAL_CATCH_TESTCASE_NO_REGISTRATION(INTERNAL_CATCH_UNIQUE_NAME( ____C_A_T_C_H____T_E_S_T____ )) #define CATCH_TEST_CASE_METHOD( className, ... ) INTERNAL_CATCH_TESTCASE_NO_REGISTRATION(INTERNAL_CATCH_UNIQUE_NAME( C_A_T_C_H_T_E_S_T_ ))
#define CATCH_METHOD_AS_TEST_CASE( method, ... ) #define CATCH_METHOD_AS_TEST_CASE( method, ... )
#define CATCH_REGISTER_TEST_CASE( Function, ... ) (void)(0) #define CATCH_REGISTER_TEST_CASE( Function, ... ) (void)(0)
#define CATCH_SECTION( ... ) #define CATCH_SECTION( ... )
@@ -360,7 +360,7 @@ using Catch::Detail::Approx;
#define CATCH_FAIL_CHECK( ... ) (void)(0) #define CATCH_FAIL_CHECK( ... ) (void)(0)
#define CATCH_SUCCEED( ... ) (void)(0) #define CATCH_SUCCEED( ... ) (void)(0)
#define CATCH_ANON_TEST_CASE() INTERNAL_CATCH_TESTCASE_NO_REGISTRATION(INTERNAL_CATCH_UNIQUE_NAME( ____C_A_T_C_H____T_E_S_T____ )) #define CATCH_ANON_TEST_CASE() INTERNAL_CATCH_TESTCASE_NO_REGISTRATION(INTERNAL_CATCH_UNIQUE_NAME( C_A_T_C_H_T_E_S_T_ ))
#ifndef CATCH_CONFIG_TRADITIONAL_MSVC_PREPROCESSOR #ifndef CATCH_CONFIG_TRADITIONAL_MSVC_PREPROCESSOR
#define CATCH_TEMPLATE_TEST_CASE( ... ) INTERNAL_CATCH_TEMPLATE_TEST_CASE_NO_REGISTRATION(__VA_ARGS__) #define CATCH_TEMPLATE_TEST_CASE( ... ) INTERNAL_CATCH_TEMPLATE_TEST_CASE_NO_REGISTRATION(__VA_ARGS__)
@@ -383,8 +383,8 @@ using Catch::Detail::Approx;
#endif #endif
// "BDD-style" convenience wrappers // "BDD-style" convenience wrappers
#define CATCH_SCENARIO( ... ) INTERNAL_CATCH_TESTCASE_NO_REGISTRATION(INTERNAL_CATCH_UNIQUE_NAME( ____C_A_T_C_H____T_E_S_T____ )) #define CATCH_SCENARIO( ... ) INTERNAL_CATCH_TESTCASE_NO_REGISTRATION(INTERNAL_CATCH_UNIQUE_NAME( C_A_T_C_H_T_E_S_T_ ))
#define CATCH_SCENARIO_METHOD( className, ... ) INTERNAL_CATCH_TESTCASE_METHOD_NO_REGISTRATION(INTERNAL_CATCH_UNIQUE_NAME( ____C_A_T_C_H____T_E_S_T____ ), className ) #define CATCH_SCENARIO_METHOD( className, ... ) INTERNAL_CATCH_TESTCASE_METHOD_NO_REGISTRATION(INTERNAL_CATCH_UNIQUE_NAME( C_A_T_C_H_T_E_S_T_ ), className )
#define CATCH_GIVEN( desc ) #define CATCH_GIVEN( desc )
#define CATCH_AND_GIVEN( desc ) #define CATCH_AND_GIVEN( desc )
#define CATCH_WHEN( desc ) #define CATCH_WHEN( desc )
@@ -435,8 +435,8 @@ using Catch::Detail::Approx;
#define WARN( msg ) (void)(0) #define WARN( msg ) (void)(0)
#define CAPTURE( msg ) (void)(0) #define CAPTURE( msg ) (void)(0)
#define TEST_CASE( ... ) INTERNAL_CATCH_TESTCASE_NO_REGISTRATION(INTERNAL_CATCH_UNIQUE_NAME( ____C_A_T_C_H____T_E_S_T____ )) #define TEST_CASE( ... ) INTERNAL_CATCH_TESTCASE_NO_REGISTRATION(INTERNAL_CATCH_UNIQUE_NAME( C_A_T_C_H_T_E_S_T_ ))
#define TEST_CASE_METHOD( className, ... ) INTERNAL_CATCH_TESTCASE_NO_REGISTRATION(INTERNAL_CATCH_UNIQUE_NAME( ____C_A_T_C_H____T_E_S_T____ )) #define TEST_CASE_METHOD( className, ... ) INTERNAL_CATCH_TESTCASE_NO_REGISTRATION(INTERNAL_CATCH_UNIQUE_NAME( C_A_T_C_H_T_E_S_T_ ))
#define METHOD_AS_TEST_CASE( method, ... ) #define METHOD_AS_TEST_CASE( method, ... )
#define REGISTER_TEST_CASE( Function, ... ) (void)(0) #define REGISTER_TEST_CASE( Function, ... ) (void)(0)
#define SECTION( ... ) #define SECTION( ... )
@@ -444,7 +444,7 @@ using Catch::Detail::Approx;
#define FAIL( ... ) (void)(0) #define FAIL( ... ) (void)(0)
#define FAIL_CHECK( ... ) (void)(0) #define FAIL_CHECK( ... ) (void)(0)
#define SUCCEED( ... ) (void)(0) #define SUCCEED( ... ) (void)(0)
#define ANON_TEST_CASE() INTERNAL_CATCH_TESTCASE_NO_REGISTRATION(INTERNAL_CATCH_UNIQUE_NAME( ____C_A_T_C_H____T_E_S_T____ )) #define ANON_TEST_CASE() INTERNAL_CATCH_TESTCASE_NO_REGISTRATION(INTERNAL_CATCH_UNIQUE_NAME( C_A_T_C_H_T_E_S_T_ ))
#ifndef CATCH_CONFIG_TRADITIONAL_MSVC_PREPROCESSOR #ifndef CATCH_CONFIG_TRADITIONAL_MSVC_PREPROCESSOR
#define TEMPLATE_TEST_CASE( ... ) INTERNAL_CATCH_TEMPLATE_TEST_CASE_NO_REGISTRATION(__VA_ARGS__) #define TEMPLATE_TEST_CASE( ... ) INTERNAL_CATCH_TEMPLATE_TEST_CASE_NO_REGISTRATION(__VA_ARGS__)
@@ -474,8 +474,8 @@ using Catch::Detail::Approx;
#define CATCH_TRANSLATE_EXCEPTION( signature ) INTERNAL_CATCH_TRANSLATE_EXCEPTION_NO_REG( INTERNAL_CATCH_UNIQUE_NAME( catch_internal_ExceptionTranslator ), signature ) #define CATCH_TRANSLATE_EXCEPTION( signature ) INTERNAL_CATCH_TRANSLATE_EXCEPTION_NO_REG( INTERNAL_CATCH_UNIQUE_NAME( catch_internal_ExceptionTranslator ), signature )
// "BDD-style" convenience wrappers // "BDD-style" convenience wrappers
#define SCENARIO( ... ) INTERNAL_CATCH_TESTCASE_NO_REGISTRATION(INTERNAL_CATCH_UNIQUE_NAME( ____C_A_T_C_H____T_E_S_T____ ) ) #define SCENARIO( ... ) INTERNAL_CATCH_TESTCASE_NO_REGISTRATION(INTERNAL_CATCH_UNIQUE_NAME( C_A_T_C_H_T_E_S_T_ ) )
#define SCENARIO_METHOD( className, ... ) INTERNAL_CATCH_TESTCASE_METHOD_NO_REGISTRATION(INTERNAL_CATCH_UNIQUE_NAME( ____C_A_T_C_H____T_E_S_T____ ), className ) #define SCENARIO_METHOD( className, ... ) INTERNAL_CATCH_TESTCASE_METHOD_NO_REGISTRATION(INTERNAL_CATCH_UNIQUE_NAME( C_A_T_C_H_T_E_S_T_ ), className )
#define GIVEN( desc ) #define GIVEN( desc )
#define AND_GIVEN( desc ) #define AND_GIVEN( desc )

View File

@@ -667,7 +667,7 @@ namespace detail {
} }
inline auto convertInto( std::string const &source, bool &target ) -> ParserResult { inline auto convertInto( std::string const &source, bool &target ) -> ParserResult {
std::string srcLC = source; std::string srcLC = source;
std::transform( srcLC.begin(), srcLC.end(), srcLC.begin(), []( char c ) { return static_cast<char>( std::tolower(c) ); } ); std::transform( srcLC.begin(), srcLC.end(), srcLC.begin(), []( unsigned char c ) { return static_cast<char>( std::tolower(c) ); } );
if (srcLC == "y" || srcLC == "1" || srcLC == "true" || srcLC == "yes" || srcLC == "on") if (srcLC == "y" || srcLC == "1" || srcLC == "true" || srcLC == "yes" || srcLC == "on")
target = true; target = true;
else if (srcLC == "n" || srcLC == "0" || srcLC == "false" || srcLC == "no" || srcLC == "off") else if (srcLC == "n" || srcLC == "0" || srcLC == "false" || srcLC == "no" || srcLC == "off")

View File

@@ -19,6 +19,7 @@
#include "detail/catch_run_for_at_least.hpp" #include "detail/catch_run_for_at_least.hpp"
#include <algorithm> #include <algorithm>
#include <iterator>
namespace Catch { namespace Catch {
namespace Benchmark { namespace Benchmark {

View File

@@ -12,6 +12,7 @@
#define TWOBLUECUBES_CATCH_DETAIL_COMPLETE_INVOKE_HPP_INCLUDED #define TWOBLUECUBES_CATCH_DETAIL_COMPLETE_INVOKE_HPP_INCLUDED
#include "../../catch_enforce.h" #include "../../catch_enforce.h"
#include "../../catch_meta.hpp"
#include <type_traits> #include <type_traits>
#include <utility> #include <utility>
@@ -42,20 +43,18 @@ namespace Catch {
return {}; return {};
} }
}; };
template <typename Sig>
using ResultOf_t = typename std::result_of<Sig>::type;
// invoke and not return void :( // invoke and not return void :(
template <typename Fun, typename... Args> template <typename Fun, typename... Args>
CompleteType_t<ResultOf_t<Fun(Args...)>> complete_invoke(Fun&& fun, Args&&... args) { CompleteType_t<FunctionReturnType<Fun, Args...>> complete_invoke(Fun&& fun, Args&&... args) {
return CompleteInvoker<ResultOf_t<Fun(Args...)>>::invoke(std::forward<Fun>(fun), std::forward<Args>(args)...); return CompleteInvoker<FunctionReturnType<Fun, Args...>>::invoke(std::forward<Fun>(fun), std::forward<Args>(args)...);
} }
const std::string benchmarkErrorMsg = "a benchmark failed to run successfully"; const std::string benchmarkErrorMsg = "a benchmark failed to run successfully";
} // namespace Detail } // namespace Detail
template <typename Fun> template <typename Fun>
Detail::CompleteType_t<Detail::ResultOf_t<Fun()>> user_code(Fun&& fun) { Detail::CompleteType_t<FunctionReturnType<Fun>> user_code(Fun&& fun) {
CATCH_TRY{ CATCH_TRY{
return Detail::complete_invoke(std::forward<Fun>(fun)); return Detail::complete_invoke(std::forward<Fun>(fun));
} CATCH_CATCH_ALL{ } CATCH_CATCH_ALL{

View File

@@ -68,7 +68,9 @@ namespace Catch {
} }
template <typename Clock> template <typename Clock>
EnvironmentEstimate<FloatDuration<Clock>> estimate_clock_cost(FloatDuration<Clock> resolution) { EnvironmentEstimate<FloatDuration<Clock>> estimate_clock_cost(FloatDuration<Clock> resolution) {
auto time_limit = std::min(resolution * clock_cost_estimation_tick_limit, FloatDuration<Clock>(clock_cost_estimation_time_limit)); auto time_limit = (std::min)(
resolution * clock_cost_estimation_tick_limit,
FloatDuration<Clock>(clock_cost_estimation_time_limit));
auto time_clock = [](int k) { auto time_clock = [](int k) {
return Detail::measure<Clock>([k] { return Detail::measure<Clock>([k] {
for (int i = 0; i < k; ++i) { for (int i = 0; i < k; ++i) {

View File

@@ -21,7 +21,7 @@ namespace Catch {
namespace Benchmark { namespace Benchmark {
namespace Detail { namespace Detail {
template <typename Clock, typename Fun, typename... Args> template <typename Clock, typename Fun, typename... Args>
TimingOf<Clock, Fun(Args...)> measure(Fun&& fun, Args&&... args) { TimingOf<Clock, Fun, Args...> measure(Fun&& fun, Args&&... args) {
auto start = Clock::now(); auto start = Clock::now();
auto&& r = Detail::complete_invoke(fun, std::forward<Args>(args)...); auto&& r = Detail::complete_invoke(fun, std::forward<Args>(args)...);
auto end = Clock::now(); auto end = Clock::now();

View File

@@ -25,11 +25,11 @@ namespace Catch {
namespace Benchmark { namespace Benchmark {
namespace Detail { namespace Detail {
template <typename Clock, typename Fun> template <typename Clock, typename Fun>
TimingOf<Clock, Fun(int)> measure_one(Fun&& fun, int iters, std::false_type) { TimingOf<Clock, Fun, int> measure_one(Fun&& fun, int iters, std::false_type) {
return Detail::measure<Clock>(fun, iters); return Detail::measure<Clock>(fun, iters);
} }
template <typename Clock, typename Fun> template <typename Clock, typename Fun>
TimingOf<Clock, Fun(Chronometer)> measure_one(Fun&& fun, int iters, std::true_type) { TimingOf<Clock, Fun, Chronometer> measure_one(Fun&& fun, int iters, std::true_type) {
Detail::ChronometerModel<Clock> meter; Detail::ChronometerModel<Clock> meter;
auto&& result = Detail::complete_invoke(fun, Chronometer(meter, iters)); auto&& result = Detail::complete_invoke(fun, Chronometer(meter, iters));
@@ -46,7 +46,7 @@ namespace Catch {
}; };
template <typename Clock, typename Fun> template <typename Clock, typename Fun>
TimingOf<Clock, Fun(run_for_at_least_argument_t<Clock, Fun>)> run_for_at_least(ClockDuration<Clock> how_long, int seed, Fun&& fun) { TimingOf<Clock, Fun, run_for_at_least_argument_t<Clock, Fun>> run_for_at_least(ClockDuration<Clock> how_long, int seed, Fun&& fun) {
auto iters = seed; auto iters = seed;
while (iters < (1 << 30)) { while (iters < (1 << 30)) {
auto&& Timing = measure_one<Clock>(fun, iters, is_callable<Fun(Chronometer)>()); auto&& Timing = measure_one<Clock>(fun, iters, is_callable<Fun(Chronometer)>());
@@ -56,7 +56,7 @@ namespace Catch {
} }
iters *= 2; iters *= 2;
} }
throw optimized_away_error{}; Catch::throw_exception(optimized_away_error{});
} }
} // namespace Detail } // namespace Detail
} // namespace Benchmark } // namespace Benchmark

View File

@@ -152,7 +152,7 @@ namespace Catch {
double sb = stddev.point; double sb = stddev.point;
double mn = mean.point / n; double mn = mean.point / n;
double mg_min = mn / 2.; double mg_min = mn / 2.;
double sg = std::min(mg_min / 4., sb / std::sqrt(n)); double sg = (std::min)(mg_min / 4., sb / std::sqrt(n));
double sg2 = sg * sg; double sg2 = sg * sg;
double sb2 = sb * sb; double sb2 = sb * sb;
@@ -171,7 +171,7 @@ namespace Catch {
return (nc / n) * (sb2 - nc * sg2); return (nc / n) * (sb2 - nc * sg2);
}; };
return std::min(var_out(1), var_out(std::min(c_max(0.), c_max(mg_min)))) / sb2; return (std::min)(var_out(1), var_out((std::min)(c_max(0.), c_max(mg_min)))) / sb2;
} }

View File

@@ -138,8 +138,8 @@ namespace Catch {
double b2 = bias - z1; double b2 = bias - z1;
double a1 = a(b1); double a1 = a(b1);
double a2 = a(b2); double a2 = a(b2);
auto lo = std::max(cumn(a1), 0); auto lo = (std::max)(cumn(a1), 0);
auto hi = std::min(cumn(a2), n - 1); auto hi = (std::min)(cumn(a2), n - 1);
return { point, resample[lo], resample[hi], confidence_level }; return { point, resample[lo], resample[hi], confidence_level };
} }

View File

@@ -25,8 +25,8 @@ namespace Catch {
Result result; Result result;
int iterations; int iterations;
}; };
template <typename Clock, typename Sig> template <typename Clock, typename Func, typename... Args>
using TimingOf = Timing<ClockDuration<Clock>, Detail::CompleteType_t<Detail::ResultOf_t<Sig>>>; using TimingOf = Timing<ClockDuration<Clock>, Detail::CompleteType_t<FunctionReturnType<Func, Args...>>>;
} // namespace Benchmark } // namespace Benchmark
} // namespace Catch } // namespace Catch

View File

@@ -33,7 +33,7 @@ namespace Detail {
Approx operator-() const; Approx operator-() const;
template <typename T, typename = typename std::enable_if<std::is_constructible<double, T>::value>::type> template <typename T, typename = typename std::enable_if<std::is_constructible<double, T>::value>::type>
Approx operator()( T const& value ) { Approx operator()( T const& value ) const {
Approx approx( static_cast<double>(value) ); Approx approx( static_cast<double>(value) );
approx.m_epsilon = m_epsilon; approx.m_epsilon = m_epsilon;
approx.m_margin = m_margin; approx.m_margin = m_margin;

View File

@@ -15,6 +15,7 @@
#include "catch_interfaces_registry_hub.h" #include "catch_interfaces_registry_hub.h"
#include "catch_capture_matchers.h" #include "catch_capture_matchers.h"
#include "catch_run_context.h" #include "catch_run_context.h"
#include "catch_enforce.h"
namespace Catch { namespace Catch {

View File

@@ -170,6 +170,9 @@ namespace Catch {
| Opt( [&]( bool flag ) { config.showDurations = flag ? ShowDurations::Always : ShowDurations::Never; }, "yes|no" ) | Opt( [&]( bool flag ) { config.showDurations = flag ? ShowDurations::Always : ShowDurations::Never; }, "yes|no" )
["-d"]["--durations"] ["-d"]["--durations"]
( "show test durations" ) ( "show test durations" )
| Opt( config.minDuration, "seconds" )
["-D"]["--min-duration"]
( "show test durations for tests taking at least the given number of seconds" )
| Opt( loadTestNamesFromFile, "filename" ) | Opt( loadTestNamesFromFile, "filename" )
["-f"]["--input-file"] ["-f"]["--input-file"]
( "load test names to run from a file" ) ( "load test names to run from a file" )

View File

@@ -39,13 +39,9 @@
#endif #endif
#if defined(CATCH_CPP17_OR_GREATER) // Only GCC compiler should be used in this block, so other compilers trying to
# define CATCH_INTERNAL_CONFIG_CPP17_UNCAUGHT_EXCEPTIONS // mask themselves as GCC should be ignored.
#endif #if defined(__GNUC__) && !defined(__clang__) && !defined(__ICC) && !defined(__CUDACC__) && !defined(__LCC__)
// 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_START_WARNINGS_SUPPRESSION _Pragma( "GCC diagnostic push" )
# define CATCH_INTERNAL_STOP_WARNINGS_SUPPRESSION _Pragma( "GCC diagnostic pop" ) # define CATCH_INTERNAL_STOP_WARNINGS_SUPPRESSION _Pragma( "GCC diagnostic pop" )
@@ -58,7 +54,20 @@
# define CATCH_INTERNAL_START_WARNINGS_SUPPRESSION _Pragma( "clang diagnostic push" ) # define CATCH_INTERNAL_START_WARNINGS_SUPPRESSION _Pragma( "clang diagnostic push" )
# define CATCH_INTERNAL_STOP_WARNINGS_SUPPRESSION _Pragma( "clang diagnostic pop" ) # define CATCH_INTERNAL_STOP_WARNINGS_SUPPRESSION _Pragma( "clang diagnostic pop" )
# define CATCH_INTERNAL_IGNORE_BUT_WARN(...) (void)__builtin_constant_p(__VA_ARGS__) // As of this writing, IBM XL's implementation of __builtin_constant_p has a bug
// which results in calls to destructors being emitted for each temporary,
// without a matching initialization. In practice, this can result in something
// like `std::string::~string` being called on an uninitialized value.
//
// For example, this code will likely segfault under IBM XL:
// ```
// REQUIRE(std::string("12") + "34" == "1234")
// ```
//
// Therefore, `CATCH_INTERNAL_IGNORE_BUT_WARN` is not implemented.
# if !defined(__ibmxl__) && !defined(__CUDACC__)
# define CATCH_INTERNAL_IGNORE_BUT_WARN(...) (void)__builtin_constant_p(__VA_ARGS__) /* NOLINT(cppcoreguidelines-pro-type-vararg, hicpp-vararg) */
# endif
# define CATCH_INTERNAL_SUPPRESS_GLOBALS_WARNINGS \ # define CATCH_INTERNAL_SUPPRESS_GLOBALS_WARNINGS \
@@ -137,13 +146,6 @@
// Visual C++ // Visual C++
#if defined(_MSC_VER) #if defined(_MSC_VER)
# define CATCH_INTERNAL_START_WARNINGS_SUPPRESSION __pragma( warning(push) )
# define CATCH_INTERNAL_STOP_WARNINGS_SUPPRESSION __pragma( warning(pop) )
# if _MSC_VER >= 1900 // Visual Studio 2015 or newer
# define CATCH_INTERNAL_CONFIG_CPP17_UNCAUGHT_EXCEPTIONS
# endif
// Universal Windows platform does not support SEH // Universal Windows platform does not support SEH
// Or console colours (or console at all...) // Or console colours (or console at all...)
# if defined(WINAPI_FAMILY) && (WINAPI_FAMILY == WINAPI_FAMILY_APP) # if defined(WINAPI_FAMILY) && (WINAPI_FAMILY == WINAPI_FAMILY_APP)
@@ -152,13 +154,18 @@
# define CATCH_INTERNAL_CONFIG_WINDOWS_SEH # define CATCH_INTERNAL_CONFIG_WINDOWS_SEH
# endif # endif
# if !defined(__clang__) // Handle Clang masquerading for msvc
// 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 // MSVC_TRADITIONAL # endif // MSVC_TRADITIONAL
// Only do this if we're not using clang on Windows, which uses `diagnostic push` & `diagnostic pop`
# define CATCH_INTERNAL_START_WARNINGS_SUPPRESSION __pragma( warning(push) )
# define CATCH_INTERNAL_STOP_WARNINGS_SUPPRESSION __pragma( warning(pop) )
# endif // __clang__ # endif // __clang__
#endif // _MSC_VER #endif // _MSC_VER
@@ -227,7 +234,10 @@
// Check if byte is available and usable // Check if byte is available and usable
# if __has_include(<cstddef>) && defined(CATCH_CPP17_OR_GREATER) # if __has_include(<cstddef>) && defined(CATCH_CPP17_OR_GREATER)
# define CATCH_INTERNAL_CONFIG_CPP17_BYTE # include <cstddef>
# if defined(__cpp_lib_byte) && (__cpp_lib_byte > 0)
# define CATCH_INTERNAL_CONFIG_CPP17_BYTE
# endif
# endif // __has_include(<cstddef>) && defined(CATCH_CPP17_OR_GREATER) # endif // __has_include(<cstddef>) && defined(CATCH_CPP17_OR_GREATER)
// Check if variant is available and usable // Check if variant is available and usable
@@ -271,10 +281,6 @@
# define CATCH_CONFIG_CPP17_OPTIONAL # define CATCH_CONFIG_CPP17_OPTIONAL
#endif #endif
#if defined(CATCH_INTERNAL_CONFIG_CPP17_UNCAUGHT_EXCEPTIONS) && !defined(CATCH_CONFIG_NO_CPP17_UNCAUGHT_EXCEPTIONS) && !defined(CATCH_CONFIG_CPP17_UNCAUGHT_EXCEPTIONS)
# define CATCH_CONFIG_CPP17_UNCAUGHT_EXCEPTIONS
#endif
#if defined(CATCH_INTERNAL_CONFIG_CPP17_STRING_VIEW) && !defined(CATCH_CONFIG_NO_CPP17_STRING_VIEW) && !defined(CATCH_CONFIG_CPP17_STRING_VIEW) #if defined(CATCH_INTERNAL_CONFIG_CPP17_STRING_VIEW) && !defined(CATCH_CONFIG_NO_CPP17_STRING_VIEW) && !defined(CATCH_CONFIG_CPP17_STRING_VIEW)
# define CATCH_CONFIG_CPP17_STRING_VIEW # define CATCH_CONFIG_CPP17_STRING_VIEW
#endif #endif

View File

@@ -64,6 +64,7 @@ namespace Catch {
bool Config::warnAboutMissingAssertions() const { return !!(m_data.warnings & WarnAbout::NoAssertions); } bool Config::warnAboutMissingAssertions() const { return !!(m_data.warnings & WarnAbout::NoAssertions); }
bool Config::warnAboutNoTests() const { return !!(m_data.warnings & WarnAbout::NoTests); } bool Config::warnAboutNoTests() const { return !!(m_data.warnings & WarnAbout::NoTests); }
ShowDurations::OrNot Config::showDurations() const { return m_data.showDurations; } ShowDurations::OrNot Config::showDurations() const { return m_data.showDurations; }
double Config::minDuration() const { return m_data.minDuration; }
RunTests::InWhatOrder Config::runOrder() const { return m_data.runOrder; } RunTests::InWhatOrder Config::runOrder() const { return m_data.runOrder; }
unsigned int Config::rngSeed() const { return m_data.rngSeed; } unsigned int Config::rngSeed() const { return m_data.rngSeed; }
UseColour::YesOrNo Config::useColour() const { return m_data.useColour; } UseColour::YesOrNo Config::useColour() const { return m_data.useColour; }

View File

@@ -52,6 +52,7 @@ namespace Catch {
Verbosity verbosity = Verbosity::Normal; Verbosity verbosity = Verbosity::Normal;
WarnAbout::What warnings = WarnAbout::Nothing; WarnAbout::What warnings = WarnAbout::Nothing;
ShowDurations::OrNot showDurations = ShowDurations::DefaultForReporter; ShowDurations::OrNot showDurations = ShowDurations::DefaultForReporter;
double minDuration = -1;
RunTests::InWhatOrder runOrder = RunTests::InDeclarationOrder; RunTests::InWhatOrder runOrder = RunTests::InDeclarationOrder;
UseColour::YesOrNo useColour = UseColour::Auto; UseColour::YesOrNo useColour = UseColour::Auto;
WaitForKeypress::When waitForKeypress = WaitForKeypress::Never; WaitForKeypress::When waitForKeypress = WaitForKeypress::Never;
@@ -103,6 +104,7 @@ namespace Catch {
bool warnAboutMissingAssertions() const override; bool warnAboutMissingAssertions() const override;
bool warnAboutNoTests() const override; bool warnAboutNoTests() const override;
ShowDurations::OrNot showDurations() const override; ShowDurations::OrNot showDurations() const override;
double minDuration() const override;
RunTests::InWhatOrder runOrder() const override; RunTests::InWhatOrder runOrder() const override;
unsigned int rngSeed() const override; unsigned int rngSeed() const override;
UseColour::YesOrNo useColour() const override; UseColour::YesOrNo useColour() const override;

View File

@@ -0,0 +1,44 @@
// Copyright Catch2 Authors
// Distributed under the Boost Software License, Version 1.0.
// (See accompanying file LICENSE_1_0.txt or copy at
// https://www.boost.org/LICENSE_1_0.txt)
// SPDX-License-Identifier: BSL-1.0
/** \file
* Wrapper for UNCAUGHT_EXCEPTIONS configuration option
*
* For some functionality, Catch2 requires to know whether there is
* an active exception. Because `std::uncaught_exception` is deprecated
* in C++17, we want to use `std::uncaught_exceptions` if possible.
*/
#ifndef CATCH_CONFIG_UNCAUGHT_EXCEPTIONS_HPP
#define CATCH_CONFIG_UNCAUGHT_EXCEPTIONS_HPP
#if defined(_MSC_VER)
# if _MSC_VER >= 1900 // Visual Studio 2015 or newer
# define CATCH_INTERNAL_CONFIG_CPP17_UNCAUGHT_EXCEPTIONS
# endif
#endif
#include <exception>
#if defined(__cpp_lib_uncaught_exceptions) \
&& !defined(CATCH_INTERNAL_CONFIG_CPP17_UNCAUGHT_EXCEPTIONS)
# define CATCH_INTERNAL_CONFIG_CPP17_UNCAUGHT_EXCEPTIONS
#endif // __cpp_lib_uncaught_exceptions
#if defined(CATCH_INTERNAL_CONFIG_CPP17_UNCAUGHT_EXCEPTIONS) \
&& !defined(CATCH_CONFIG_NO_CPP17_UNCAUGHT_EXCEPTIONS) \
&& !defined(CATCH_CONFIG_CPP17_UNCAUGHT_EXCEPTIONS)
# define CATCH_CONFIG_CPP17_UNCAUGHT_EXCEPTIONS
#endif
#endif // CATCH_CONFIG_UNCAUGHT_EXCEPTIONS_HPP

View File

@@ -14,8 +14,7 @@
#if defined(CATCH_PLATFORM_MAC) || defined(CATCH_PLATFORM_IPHONE) #if defined(CATCH_PLATFORM_MAC) || defined(CATCH_PLATFORM_IPHONE)
# include <assert.h> # include <cassert>
# include <stdbool.h>
# include <sys/types.h> # include <sys/types.h>
# include <unistd.h> # include <unistd.h>
# include <cstddef> # include <cstddef>

View File

@@ -17,7 +17,11 @@ namespace Catch {
#ifdef CATCH_PLATFORM_MAC #ifdef CATCH_PLATFORM_MAC
#define CATCH_TRAP() __asm__("int $3\n" : : ) /* NOLINT */ #if defined(__i386__) || defined(__x86_64__)
#define CATCH_TRAP() __asm__("int $3\n" : : ) /* NOLINT */
#elif defined(__aarch64__)
#define CATCH_TRAP() __asm__(".inst 0xd4200000")
#endif
#elif defined(CATCH_PLATFORM_IPHONE) #elif defined(CATCH_PLATFORM_IPHONE)

View File

@@ -200,6 +200,18 @@ namespace Catch {
auto operator <= ( RhsT const& rhs ) -> BinaryExpr<LhsT, RhsT const&> const { auto operator <= ( RhsT const& rhs ) -> BinaryExpr<LhsT, RhsT const&> const {
return { static_cast<bool>(m_lhs <= rhs), m_lhs, "<=", rhs }; return { static_cast<bool>(m_lhs <= rhs), m_lhs, "<=", rhs };
} }
template <typename RhsT>
auto operator | (RhsT const& rhs) -> BinaryExpr<LhsT, RhsT const&> const {
return { static_cast<bool>(m_lhs | rhs), m_lhs, "|", rhs };
}
template <typename RhsT>
auto operator & (RhsT const& rhs) -> BinaryExpr<LhsT, RhsT const&> const {
return { static_cast<bool>(m_lhs & rhs), m_lhs, "&", rhs };
}
template <typename RhsT>
auto operator ^ (RhsT const& rhs) -> BinaryExpr<LhsT, RhsT const&> const {
return { static_cast<bool>(m_lhs ^ rhs), m_lhs, "^", rhs };
}
template<typename RhsT> template<typename RhsT>
auto operator && ( RhsT const& ) -> BinaryExpr<LhsT, RhsT const&> const { auto operator && ( RhsT const& ) -> BinaryExpr<LhsT, RhsT const&> const {

View File

@@ -22,7 +22,7 @@ namespace Catch {
// Extracts the actual name part of an enum instance // Extracts the actual name part of an enum instance
// In other words, it returns the Blue part of Bikeshed::Colour::Blue // In other words, it returns the Blue part of Bikeshed::Colour::Blue
StringRef extractInstanceName(StringRef enumInstance) { StringRef extractInstanceName(StringRef enumInstance) {
// Find last occurence of ":" // Find last occurrence of ":"
size_t name_start = enumInstance.size(); size_t name_start = enumInstance.size();
while (name_start > 0 && enumInstance[name_start - 1] != ':') { while (name_start > 0 && enumInstance[name_start - 1] != ':') {
--name_start; --name_start;

View File

@@ -7,30 +7,72 @@
* *
*/ */
/** \file
* This file provides platform specific implementations of FatalConditionHandler
*
* This means that there is a lot of conditional compilation, and platform
* specific code. Currently, Catch2 supports a dummy handler (if no
* handler is desired), and 2 platform specific handlers:
* * Windows' SEH
* * POSIX signals
*
* Consequently, various pieces of code below are compiled if either of
* the platform specific handlers is enabled, or if none of them are
* enabled. It is assumed that both cannot be enabled at the same time,
* and doing so should cause a compilation error.
*
* If another platform specific handler is added, the compile guards
* below will need to be updated taking these assumptions into account.
*/
#include "catch_fatal_condition.h" #include "catch_fatal_condition.h"
#include "catch_context.h" #include "catch_context.h"
#include "catch_interfaces_capture.h" #include "catch_enforce.h"
#include "catch_run_context.h"
#include "catch_windows_h_proxy.h"
#if defined(__GNUC__) #include <algorithm>
# pragma GCC diagnostic push
# pragma GCC diagnostic ignored "-Wmissing-field-initializers" #if !defined( CATCH_CONFIG_WINDOWS_SEH ) && !defined( CATCH_CONFIG_POSIX_SIGNALS )
#endif
namespace Catch {
// If neither SEH nor signal handling is required, the handler impls
// do not have to do anything, and can be empty.
void FatalConditionHandler::engage_platform() {}
void FatalConditionHandler::disengage_platform() {}
FatalConditionHandler::FatalConditionHandler() = default;
FatalConditionHandler::~FatalConditionHandler() = default;
} // end namespace Catch
#endif // !CATCH_CONFIG_WINDOWS_SEH && !CATCH_CONFIG_POSIX_SIGNALS
#if defined( CATCH_CONFIG_WINDOWS_SEH ) && defined( CATCH_CONFIG_POSIX_SIGNALS )
#error "Inconsistent configuration: Windows' SEH handling and POSIX signals cannot be enabled at the same time"
#endif // CATCH_CONFIG_WINDOWS_SEH && CATCH_CONFIG_POSIX_SIGNALS
#if defined( CATCH_CONFIG_WINDOWS_SEH ) || defined( CATCH_CONFIG_POSIX_SIGNALS ) #if defined( CATCH_CONFIG_WINDOWS_SEH ) || defined( CATCH_CONFIG_POSIX_SIGNALS )
namespace { namespace {
// Report the error condition //! Signals fatal error message to the run context
void reportFatal( char const * const message ) { void reportFatal( char const * const message ) {
Catch::getCurrentContext().getResultCapture()->handleFatalErrorCondition( message ); Catch::getCurrentContext().getResultCapture()->handleFatalErrorCondition( message );
} }
}
#endif // signals/SEH handling //! Minimal size Catch2 needs for its own fatal error handling.
//! Picked anecdotally, so it might not be sufficient on all
//! platforms, and for all configurations.
constexpr std::size_t minStackSizeForErrors = 32 * 1024;
} // end unnamed namespace
#endif // CATCH_CONFIG_WINDOWS_SEH || CATCH_CONFIG_POSIX_SIGNALS
#if defined( CATCH_CONFIG_WINDOWS_SEH ) #if defined( CATCH_CONFIG_WINDOWS_SEH )
namespace Catch { namespace Catch {
struct SignalDefs { DWORD id; const char* name; }; struct SignalDefs { DWORD id; const char* name; };
// There is no 1-1 mapping between signals and windows exceptions. // There is no 1-1 mapping between signals and windows exceptions.
@@ -43,7 +85,7 @@ namespace Catch {
{ static_cast<DWORD>(EXCEPTION_INT_DIVIDE_BY_ZERO), "Divide by zero error" }, { static_cast<DWORD>(EXCEPTION_INT_DIVIDE_BY_ZERO), "Divide by zero error" },
}; };
LONG CALLBACK FatalConditionHandler::handleVectoredException(PEXCEPTION_POINTERS ExceptionInfo) { static LONG CALLBACK handleVectoredException(PEXCEPTION_POINTERS ExceptionInfo) {
for (auto const& def : signalDefs) { for (auto const& def : signalDefs) {
if (ExceptionInfo->ExceptionRecord->ExceptionCode == def.id) { if (ExceptionInfo->ExceptionRecord->ExceptionCode == def.id) {
reportFatal(def.name); reportFatal(def.name);
@@ -54,39 +96,52 @@ namespace Catch {
return EXCEPTION_CONTINUE_SEARCH; return EXCEPTION_CONTINUE_SEARCH;
} }
FatalConditionHandler::FatalConditionHandler() { // Since we do not support multiple instantiations, we put these
isSet = true; // into global variables and rely on cleaning them up in outlined
// 32k seems enough for Catch to handle stack overflow, // constructors/destructors
// but the value was found experimentally, so there is no strong guarantee static PVOID exceptionHandlerHandle = nullptr;
guaranteeSize = 32 * 1024;
exceptionHandlerHandle = nullptr;
// Register as first handler in current chain
exceptionHandlerHandle = AddVectoredExceptionHandler(1, handleVectoredException);
// Pass in guarantee size to be filled
SetThreadStackGuarantee(&guaranteeSize);
}
void FatalConditionHandler::reset() {
if (isSet) { // For MSVC, we reserve part of the stack memory for handling
RemoveVectoredExceptionHandler(exceptionHandlerHandle); // memory overflow structured exception.
SetThreadStackGuarantee(&guaranteeSize); FatalConditionHandler::FatalConditionHandler() {
exceptionHandlerHandle = nullptr; ULONG guaranteeSize = static_cast<ULONG>(minStackSizeForErrors);
isSet = false; if (!SetThreadStackGuarantee(&guaranteeSize)) {
// We do not want to fully error out, because needing
// the stack reserve should be rare enough anyway.
Catch::cerr()
<< "Failed to reserve piece of stack."
<< " Stack overflows will not be reported successfully.";
} }
} }
FatalConditionHandler::~FatalConditionHandler() { // We do not attempt to unset the stack guarantee, because
reset(); // Windows does not support lowering the stack size guarantee.
FatalConditionHandler::~FatalConditionHandler() = default;
void FatalConditionHandler::engage_platform() {
// Register as first handler in current chain
exceptionHandlerHandle = AddVectoredExceptionHandler(1, handleVectoredException);
if (!exceptionHandlerHandle) {
CATCH_RUNTIME_ERROR("Could not register vectored exception handler");
}
} }
bool FatalConditionHandler::isSet = false; void FatalConditionHandler::disengage_platform() {
ULONG FatalConditionHandler::guaranteeSize = 0; if (!RemoveVectoredExceptionHandler(exceptionHandlerHandle)) {
PVOID FatalConditionHandler::exceptionHandlerHandle = nullptr; CATCH_RUNTIME_ERROR("Could not unregister vectored exception handler");
}
exceptionHandlerHandle = nullptr;
}
} // end namespace Catch
} // namespace Catch #endif // CATCH_CONFIG_WINDOWS_SEH
#elif defined( CATCH_CONFIG_POSIX_SIGNALS ) #if defined( CATCH_CONFIG_POSIX_SIGNALS )
#include <signal.h>
namespace Catch { namespace Catch {
@@ -94,10 +149,6 @@ namespace Catch {
int id; int id;
const char* name; const char* name;
}; };
// 32kb for the alternate stack seems to be sufficient. However, this value
// is experimentally determined, so that's not guaranteed.
static constexpr std::size_t sigStackSize = 32768 >= MINSIGSTKSZ ? 32768 : MINSIGSTKSZ;
static SignalDefs signalDefs[] = { static SignalDefs signalDefs[] = {
{ SIGINT, "SIGINT - Terminal interrupt signal" }, { SIGINT, "SIGINT - Terminal interrupt signal" },
@@ -108,8 +159,32 @@ namespace Catch {
{ SIGABRT, "SIGABRT - Abort (abnormal termination) signal" } { SIGABRT, "SIGABRT - Abort (abnormal termination) signal" }
}; };
// Older GCCs trigger -Wmissing-field-initializers for T foo = {}
// which is zero initialization, but not explicit. We want to avoid
// that.
#if defined(__GNUC__)
# pragma GCC diagnostic push
# pragma GCC diagnostic ignored "-Wmissing-field-initializers"
#endif
void FatalConditionHandler::handleSignal( int sig ) { static char* altStackMem = nullptr;
static std::size_t altStackSize = 0;
static stack_t oldSigStack{};
static struct sigaction oldSigActions[sizeof(signalDefs) / sizeof(SignalDefs)]{};
static void restorePreviousSignalHandlers() {
// We set signal handlers back to the previous ones. Hopefully
// nobody overwrote them in the meantime, and doesn't expect
// their signal handlers to live past ours given that they
// installed them after ours..
for (std::size_t i = 0; i < sizeof(signalDefs) / sizeof(SignalDefs); ++i) {
sigaction(signalDefs[i].id, &oldSigActions[i], nullptr);
}
// Return the old stack
sigaltstack(&oldSigStack, nullptr);
}
static void handleSignal( int sig ) {
char const * name = "<unknown signal>"; char const * name = "<unknown signal>";
for (auto const& def : signalDefs) { for (auto const& def : signalDefs) {
if (sig == def.id) { if (sig == def.id) {
@@ -117,16 +192,33 @@ namespace Catch {
break; break;
} }
} }
reset(); // We need to restore previous signal handlers and let them do
reportFatal(name); // their thing, so that the users can have the debugger break
// when a signal is raised, and so on.
restorePreviousSignalHandlers();
reportFatal( name );
raise( sig ); raise( sig );
} }
FatalConditionHandler::FatalConditionHandler() { FatalConditionHandler::FatalConditionHandler() {
isSet = true; assert(!altStackMem && "Cannot initialize POSIX signal handler when one already exists");
if (altStackSize == 0) {
altStackSize = std::max(static_cast<size_t>(SIGSTKSZ), minStackSizeForErrors);
}
altStackMem = new char[altStackSize]();
}
FatalConditionHandler::~FatalConditionHandler() {
delete[] altStackMem;
// We signal that another instance can be constructed by zeroing
// out the pointer.
altStackMem = nullptr;
}
void FatalConditionHandler::engage_platform() {
stack_t sigStack; stack_t sigStack;
sigStack.ss_sp = altStackMem; sigStack.ss_sp = altStackMem;
sigStack.ss_size = sigStackSize; sigStack.ss_size = altStackSize;
sigStack.ss_flags = 0; sigStack.ss_flags = 0;
sigaltstack(&sigStack, &oldSigStack); sigaltstack(&sigStack, &oldSigStack);
struct sigaction sa = { }; struct sigaction sa = { };
@@ -138,39 +230,15 @@ namespace Catch {
} }
} }
FatalConditionHandler::~FatalConditionHandler() {
reset();
}
void FatalConditionHandler::reset() {
if( isSet ) {
// Set signals back to previous values -- hopefully nobody overwrote them in the meantime
for( std::size_t i = 0; i < sizeof(signalDefs)/sizeof(SignalDefs); ++i ) {
sigaction(signalDefs[i].id, &oldSigActions[i], nullptr);
}
// Return the old stack
sigaltstack(&oldSigStack, nullptr);
isSet = false;
}
}
bool FatalConditionHandler::isSet = false;
struct sigaction FatalConditionHandler::oldSigActions[sizeof(signalDefs)/sizeof(SignalDefs)] = {};
stack_t FatalConditionHandler::oldSigStack = {};
char FatalConditionHandler::altStackMem[sigStackSize] = {};
} // namespace Catch
#else
namespace Catch {
void FatalConditionHandler::reset() {}
}
#endif // signals/SEH handling
#if defined(__GNUC__) #if defined(__GNUC__)
# pragma GCC diagnostic pop # pragma GCC diagnostic pop
#endif #endif
void FatalConditionHandler::disengage_platform() {
restorePreviousSignalHandlers();
}
} // end namespace Catch
#endif // CATCH_CONFIG_POSIX_SIGNALS

View File

@@ -11,59 +11,58 @@
#include "catch_platform.h" #include "catch_platform.h"
#include "catch_compiler_capabilities.h" #include "catch_compiler_capabilities.h"
#include "catch_windows_h_proxy.h"
#include <cassert>
#if defined( CATCH_CONFIG_WINDOWS_SEH )
namespace Catch { namespace Catch {
struct FatalConditionHandler { // Wrapper for platform-specific fatal error (signals/SEH) handlers
//
static LONG CALLBACK handleVectoredException(PEXCEPTION_POINTERS ExceptionInfo); // Tries to be cooperative with other handlers, and not step over
FatalConditionHandler(); // other handlers. This means that unknown structured exceptions
static void reset(); // are passed on, previous signal handlers are called, and so on.
~FatalConditionHandler(); //
// Can only be instantiated once, and assumes that once a signal
private: // is caught, the binary will end up terminating. Thus, there
static bool isSet; class FatalConditionHandler {
static ULONG guaranteeSize; bool m_started = false;
static PVOID exceptionHandlerHandle;
};
} // namespace Catch
#elif defined ( CATCH_CONFIG_POSIX_SIGNALS )
#include <signal.h>
namespace Catch {
struct FatalConditionHandler {
static bool isSet;
static struct sigaction oldSigActions[];
static stack_t oldSigStack;
static char altStackMem[];
static void handleSignal( int sig );
// Install/disengage implementation for specific platform.
// Should be if-defed to work on current platform, can assume
// engage-disengage 1:1 pairing.
void engage_platform();
void disengage_platform();
public:
// Should also have platform-specific implementations as needed
FatalConditionHandler(); FatalConditionHandler();
~FatalConditionHandler(); ~FatalConditionHandler();
static void reset();
void engage() {
assert(!m_started && "Handler cannot be installed twice.");
m_started = true;
engage_platform();
}
void disengage() {
assert(m_started && "Handler cannot be uninstalled without being installed first");
m_started = false;
disengage_platform();
}
}; };
} // namespace Catch //! Simple RAII guard for (dis)engaging the FatalConditionHandler
class FatalConditionHandlerGuard {
FatalConditionHandler* m_handler;
#else public:
FatalConditionHandlerGuard(FatalConditionHandler* handler):
namespace Catch { m_handler(handler) {
struct FatalConditionHandler { m_handler->engage();
void reset(); }
~FatalConditionHandlerGuard() {
m_handler->disengage();
}
}; };
}
#endif } // end namespace Catch
#endif // TWOBLUECUBES_CATCH_FATAL_CONDITION_H_INCLUDED #endif // TWOBLUECUBES_CATCH_FATAL_CONDITION_H_INCLUDED

View File

@@ -24,8 +24,8 @@ namespace Generators {
GeneratorUntypedBase::~GeneratorUntypedBase() {} GeneratorUntypedBase::~GeneratorUntypedBase() {}
auto acquireGeneratorTracker( SourceLineInfo const& lineInfo ) -> IGeneratorTracker& { auto acquireGeneratorTracker( StringRef generatorName, SourceLineInfo const& lineInfo ) -> IGeneratorTracker& {
return getResultCapture().acquireGeneratorTracker( lineInfo ); return getResultCapture().acquireGeneratorTracker( generatorName, lineInfo );
} }
} // namespace Generators } // namespace Generators

View File

@@ -10,6 +10,7 @@
#include "catch_interfaces_generatortracker.h" #include "catch_interfaces_generatortracker.h"
#include "catch_common.h" #include "catch_common.h"
#include "catch_enforce.h" #include "catch_enforce.h"
#include "catch_stringref.h"
#include <memory> #include <memory>
#include <vector> #include <vector>
@@ -181,16 +182,16 @@ namespace Generators {
return makeGenerators( value( T( std::forward<U>( val ) ) ), std::forward<Gs>( moreGenerators )... ); return makeGenerators( value( T( std::forward<U>( val ) ) ), std::forward<Gs>( moreGenerators )... );
} }
auto acquireGeneratorTracker( SourceLineInfo const& lineInfo ) -> IGeneratorTracker&; auto acquireGeneratorTracker( StringRef generatorName, SourceLineInfo const& lineInfo ) -> IGeneratorTracker&;
template<typename L> template<typename L>
// Note: The type after -> is weird, because VS2015 cannot parse // Note: The type after -> is weird, because VS2015 cannot parse
// the expression used in the typedef inside, when it is in // the expression used in the typedef inside, when it is in
// return type. Yeah. // return type. Yeah.
auto generate( SourceLineInfo const& lineInfo, L const& generatorExpression ) -> decltype(std::declval<decltype(generatorExpression())>().get()) { auto generate( StringRef generatorName, SourceLineInfo const& lineInfo, L const& generatorExpression ) -> decltype(std::declval<decltype(generatorExpression())>().get()) {
using UnderlyingType = typename decltype(generatorExpression())::type; using UnderlyingType = typename decltype(generatorExpression())::type;
IGeneratorTracker& tracker = acquireGeneratorTracker( lineInfo ); IGeneratorTracker& tracker = acquireGeneratorTracker( generatorName, lineInfo );
if (!tracker.hasGenerator()) { if (!tracker.hasGenerator()) {
tracker.setGenerator(pf::make_unique<Generators<UnderlyingType>>(generatorExpression())); tracker.setGenerator(pf::make_unique<Generators<UnderlyingType>>(generatorExpression()));
} }
@@ -203,10 +204,16 @@ namespace Generators {
} // namespace Catch } // namespace Catch
#define GENERATE( ... ) \ #define GENERATE( ... ) \
Catch::Generators::generate( CATCH_INTERNAL_LINEINFO, [ ]{ using namespace Catch::Generators; return makeGenerators( __VA_ARGS__ ); } ) //NOLINT(google-build-using-namespace) Catch::Generators::generate( INTERNAL_CATCH_STRINGIZE(INTERNAL_CATCH_UNIQUE_NAME(generator)), \
CATCH_INTERNAL_LINEINFO, \
[ ]{ using namespace Catch::Generators; return makeGenerators( __VA_ARGS__ ); } ) //NOLINT(google-build-using-namespace)
#define GENERATE_COPY( ... ) \ #define GENERATE_COPY( ... ) \
Catch::Generators::generate( CATCH_INTERNAL_LINEINFO, [=]{ using namespace Catch::Generators; return makeGenerators( __VA_ARGS__ ); } ) //NOLINT(google-build-using-namespace) Catch::Generators::generate( INTERNAL_CATCH_STRINGIZE(INTERNAL_CATCH_UNIQUE_NAME(generator)), \
CATCH_INTERNAL_LINEINFO, \
[=]{ using namespace Catch::Generators; return makeGenerators( __VA_ARGS__ ); } ) //NOLINT(google-build-using-namespace)
#define GENERATE_REF( ... ) \ #define GENERATE_REF( ... ) \
Catch::Generators::generate( CATCH_INTERNAL_LINEINFO, [&]{ using namespace Catch::Generators; return makeGenerators( __VA_ARGS__ ); } ) //NOLINT(google-build-using-namespace) Catch::Generators::generate( INTERNAL_CATCH_STRINGIZE(INTERNAL_CATCH_UNIQUE_NAME(generator)), \
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

View File

@@ -63,7 +63,7 @@ namespace Generators {
if (!m_predicate(m_generator.get())) { if (!m_predicate(m_generator.get())) {
// It might happen that there are no values that pass the // It might happen that there are no values that pass the
// filter. In that case we throw an exception. // filter. In that case we throw an exception.
auto has_initial_value = next(); auto has_initial_value = nextImpl();
if (!has_initial_value) { if (!has_initial_value) {
Catch::throw_exception(GeneratorException("No valid value found in filtered generator")); Catch::throw_exception(GeneratorException("No valid value found in filtered generator"));
} }
@@ -75,6 +75,11 @@ namespace Generators {
} }
bool next() override { bool next() override {
return nextImpl();
}
private:
bool nextImpl() {
bool success = m_generator.next(); bool success = m_generator.next();
if (!success) { if (!success) {
return false; return false;

View File

@@ -44,7 +44,7 @@ namespace Catch {
virtual void sectionEnded( SectionEndInfo const& endInfo ) = 0; virtual void sectionEnded( SectionEndInfo const& endInfo ) = 0;
virtual void sectionEndedEarly( SectionEndInfo const& endInfo ) = 0; virtual void sectionEndedEarly( SectionEndInfo const& endInfo ) = 0;
virtual auto acquireGeneratorTracker( SourceLineInfo const& lineInfo ) -> IGeneratorTracker& = 0; virtual auto acquireGeneratorTracker( StringRef generatorName, SourceLineInfo const& lineInfo ) -> IGeneratorTracker& = 0;
#if defined(CATCH_CONFIG_ENABLE_BENCHMARKING) #if defined(CATCH_CONFIG_ENABLE_BENCHMARKING)
virtual void benchmarkPreparing( std::string const& name ) = 0; virtual void benchmarkPreparing( std::string const& name ) = 0;

View File

@@ -69,6 +69,7 @@ namespace Catch {
virtual int abortAfter() const = 0; virtual int abortAfter() const = 0;
virtual bool showInvisibles() const = 0; virtual bool showInvisibles() const = 0;
virtual ShowDurations::OrNot showDurations() const = 0; virtual ShowDurations::OrNot showDurations() const = 0;
virtual double minDuration() const = 0;
virtual TestSpec const& testSpec() const = 0; virtual TestSpec const& testSpec() const = 0;
virtual bool hasTestFilters() const = 0; virtual bool hasTestFilters() const = 0;
virtual std::vector<std::string> const& getTestsOrTags() const = 0; virtual std::vector<std::string> const& getTestsOrTags() const = 0;

View File

@@ -46,6 +46,9 @@ namespace Catch {
{} {}
std::string translate( ExceptionTranslators::const_iterator it, ExceptionTranslators::const_iterator itEnd ) const override { std::string translate( ExceptionTranslators::const_iterator it, ExceptionTranslators::const_iterator itEnd ) const override {
#if defined(CATCH_CONFIG_DISABLE_EXCEPTIONS)
return "";
#else
try { try {
if( it == itEnd ) if( it == itEnd )
std::rethrow_exception(std::current_exception()); std::rethrow_exception(std::current_exception());
@@ -55,6 +58,7 @@ namespace Catch {
catch( T& ex ) { catch( T& ex ) {
return m_translateFunction( ex ); return m_translateFunction( ex );
} }
#endif
} }
protected: protected:

View File

@@ -21,6 +21,8 @@
#if defined(CATCH_CONFIG_ENABLE_BENCHMARKING) #if defined(CATCH_CONFIG_ENABLE_BENCHMARKING)
#include "benchmark/catch_estimate.hpp" #include "benchmark/catch_estimate.hpp"
#include "benchmark/catch_outlier_classification.hpp" #include "benchmark/catch_outlier_classification.hpp"
#include <iterator>
#endif // CATCH_CONFIG_ENABLE_BENCHMARKING #endif // CATCH_CONFIG_ENABLE_BENCHMARKING

View File

@@ -55,7 +55,8 @@ namespace {
return lhs == rhs; return lhs == rhs;
} }
auto ulpDiff = std::abs(lc - rc); // static cast as a workaround for IBM XLC
auto ulpDiff = std::abs(static_cast<FP>(lc - rc));
return static_cast<uint64_t>(ulpDiff) <= maxUlpDiff; return static_cast<uint64_t>(ulpDiff) <= maxUlpDiff;
} }
@@ -234,4 +235,3 @@ Floating::WithinRelMatcher WithinRel(float target) {
} // namespace Matchers } // namespace Matchers
} // namespace Catch } // namespace Catch

View File

@@ -17,12 +17,12 @@ namespace Catch {
namespace Matchers { namespace Matchers {
namespace Vector { namespace Vector {
template<typename T> template<typename T, typename Alloc>
struct ContainsElementMatcher : MatcherBase<std::vector<T>> { struct ContainsElementMatcher : MatcherBase<std::vector<T, Alloc>> {
ContainsElementMatcher(T const &comparator) : m_comparator( comparator) {} ContainsElementMatcher(T const &comparator) : m_comparator( comparator) {}
bool match(std::vector<T> const &v) const override { bool match(std::vector<T, Alloc> const &v) const override {
for (auto const& el : v) { for (auto const& el : v) {
if (el == m_comparator) { if (el == m_comparator) {
return true; return true;
@@ -38,12 +38,12 @@ namespace Matchers {
T const& m_comparator; T const& m_comparator;
}; };
template<typename T> template<typename T, typename AllocComp, typename AllocMatch>
struct ContainsMatcher : MatcherBase<std::vector<T>> { struct ContainsMatcher : MatcherBase<std::vector<T, AllocMatch>> {
ContainsMatcher(std::vector<T> const &comparator) : m_comparator( comparator ) {} ContainsMatcher(std::vector<T, AllocComp> const &comparator) : m_comparator( comparator ) {}
bool match(std::vector<T> const &v) const override { bool match(std::vector<T, AllocMatch> const &v) const override {
// !TBD: see note in EqualsMatcher // !TBD: see note in EqualsMatcher
if (m_comparator.size() > v.size()) if (m_comparator.size() > v.size())
return false; return false;
@@ -65,18 +65,18 @@ namespace Matchers {
return "Contains: " + ::Catch::Detail::stringify( m_comparator ); return "Contains: " + ::Catch::Detail::stringify( m_comparator );
} }
std::vector<T> const& m_comparator; std::vector<T, AllocComp> const& m_comparator;
}; };
template<typename T> template<typename T, typename AllocComp, typename AllocMatch>
struct EqualsMatcher : MatcherBase<std::vector<T>> { struct EqualsMatcher : MatcherBase<std::vector<T, AllocMatch>> {
EqualsMatcher(std::vector<T> const &comparator) : m_comparator( comparator ) {} EqualsMatcher(std::vector<T, AllocComp> const &comparator) : m_comparator( comparator ) {}
bool match(std::vector<T> const &v) const override { bool match(std::vector<T, AllocMatch> const &v) const override {
// !TBD: This currently works if all elements can be compared using != // !TBD: This currently works if all elements can be compared using !=
// - a more general approach would be via a compare template that defaults // - a more general approach would be via a compare template that defaults
// to using !=. but could be specialised for, e.g. std::vector<T> etc // to using !=. but could be specialised for, e.g. std::vector<T, Alloc> etc
// - then just call that directly // - then just call that directly
if (m_comparator.size() != v.size()) if (m_comparator.size() != v.size())
return false; return false;
@@ -88,15 +88,15 @@ namespace Matchers {
std::string describe() const override { std::string describe() const override {
return "Equals: " + ::Catch::Detail::stringify( m_comparator ); return "Equals: " + ::Catch::Detail::stringify( m_comparator );
} }
std::vector<T> const& m_comparator; std::vector<T, AllocComp> const& m_comparator;
}; };
template<typename T> template<typename T, typename AllocComp, typename AllocMatch>
struct ApproxMatcher : MatcherBase<std::vector<T>> { struct ApproxMatcher : MatcherBase<std::vector<T, AllocMatch>> {
ApproxMatcher(std::vector<T> const& comparator) : m_comparator( comparator ) {} ApproxMatcher(std::vector<T, AllocComp> const& comparator) : m_comparator( comparator ) {}
bool match(std::vector<T> const &v) const override { bool match(std::vector<T, AllocMatch> const &v) const override {
if (m_comparator.size() != v.size()) if (m_comparator.size() != v.size())
return false; return false;
for (std::size_t i = 0; i < v.size(); ++i) for (std::size_t i = 0; i < v.size(); ++i)
@@ -123,16 +123,14 @@ namespace Matchers {
return *this; return *this;
} }
std::vector<T> const& m_comparator; std::vector<T, AllocComp> const& m_comparator;
mutable Catch::Detail::Approx approx = Catch::Detail::Approx::custom(); mutable Catch::Detail::Approx approx = Catch::Detail::Approx::custom();
}; };
template<typename T> template<typename T, typename AllocComp, typename AllocMatch>
struct UnorderedEqualsMatcher : MatcherBase<std::vector<T>> { struct UnorderedEqualsMatcher : MatcherBase<std::vector<T, AllocMatch>> {
UnorderedEqualsMatcher(std::vector<T> const& target) : m_target(target) {} UnorderedEqualsMatcher(std::vector<T, AllocComp> const& target) : m_target(target) {}
bool match(std::vector<T> const& vec) const override { bool match(std::vector<T, AllocMatch> const& vec) const override {
// Note: This is a reimplementation of std::is_permutation,
// because I don't want to include <algorithm> inside the common path
if (m_target.size() != vec.size()) { if (m_target.size() != vec.size()) {
return false; return false;
} }
@@ -143,7 +141,7 @@ namespace Matchers {
return "UnorderedEquals: " + ::Catch::Detail::stringify(m_target); return "UnorderedEquals: " + ::Catch::Detail::stringify(m_target);
} }
private: private:
std::vector<T> const& m_target; std::vector<T, AllocComp> const& m_target;
}; };
} // namespace Vector } // namespace Vector
@@ -151,29 +149,29 @@ namespace Matchers {
// The following functions create the actual matcher objects. // The following functions create the actual matcher objects.
// This allows the types to be inferred // This allows the types to be inferred
template<typename T> template<typename T, typename AllocComp = std::allocator<T>, typename AllocMatch = AllocComp>
Vector::ContainsMatcher<T> Contains( std::vector<T> const& comparator ) { Vector::ContainsMatcher<T, AllocComp, AllocMatch> Contains( std::vector<T, AllocComp> const& comparator ) {
return Vector::ContainsMatcher<T>( comparator ); return Vector::ContainsMatcher<T, AllocComp, AllocMatch>( comparator );
} }
template<typename T> template<typename T, typename Alloc = std::allocator<T>>
Vector::ContainsElementMatcher<T> VectorContains( T const& comparator ) { Vector::ContainsElementMatcher<T, Alloc> VectorContains( T const& comparator ) {
return Vector::ContainsElementMatcher<T>( comparator ); return Vector::ContainsElementMatcher<T, Alloc>( comparator );
} }
template<typename T> template<typename T, typename AllocComp = std::allocator<T>, typename AllocMatch = AllocComp>
Vector::EqualsMatcher<T> Equals( std::vector<T> const& comparator ) { Vector::EqualsMatcher<T, AllocComp, AllocMatch> Equals( std::vector<T, AllocComp> const& comparator ) {
return Vector::EqualsMatcher<T>( comparator ); return Vector::EqualsMatcher<T, AllocComp, AllocMatch>( comparator );
} }
template<typename T> template<typename T, typename AllocComp = std::allocator<T>, typename AllocMatch = AllocComp>
Vector::ApproxMatcher<T> Approx( std::vector<T> const& comparator ) { Vector::ApproxMatcher<T, AllocComp, AllocMatch> Approx( std::vector<T, AllocComp> const& comparator ) {
return Vector::ApproxMatcher<T>( comparator ); return Vector::ApproxMatcher<T, AllocComp, AllocMatch>( comparator );
} }
template<typename T> template<typename T, typename AllocComp = std::allocator<T>, typename AllocMatch = AllocComp>
Vector::UnorderedEqualsMatcher<T> UnorderedEquals(std::vector<T> const& target) { Vector::UnorderedEqualsMatcher<T, AllocComp, AllocMatch> UnorderedEquals(std::vector<T, AllocComp> const& target) {
return Vector::UnorderedEqualsMatcher<T>(target); return Vector::UnorderedEqualsMatcher<T, AllocComp, AllocMatch>( target );
} }
} // namespace Matchers } // namespace Matchers

View File

@@ -69,10 +69,10 @@ namespace Catch {
Capturer::Capturer( StringRef macroName, SourceLineInfo const& lineInfo, ResultWas::OfType resultType, StringRef names ) { Capturer::Capturer( StringRef macroName, SourceLineInfo const& lineInfo, ResultWas::OfType resultType, StringRef names ) {
auto trimmed = [&] (size_t start, size_t end) { auto trimmed = [&] (size_t start, size_t end) {
while (names[start] == ',' || isspace(names[start])) { while (names[start] == ',' || isspace(static_cast<unsigned char>(names[start]))) {
++start; ++start;
} }
while (names[end] == ',' || isspace(names[end])) { while (names[end] == ',' || isspace(static_cast<unsigned char>(names[end]))) {
--end; --end;
} }
return names.substr(start, end - start + 1); return names.substr(start, end - start + 1);

View File

@@ -32,13 +32,13 @@ namespace Catch {
#if defined(__cpp_lib_is_invocable) && __cpp_lib_is_invocable >= 201703 #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 // 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 // replaced with std::invoke_result here.
// typename *::type format. template <typename Func, typename... U>
template <typename Func, typename U> using FunctionReturnType = std::remove_reference_t<std::remove_cv_t<std::invoke_result_t<Func, U...>>>;
using FunctionReturnType = std::remove_reference_t<std::remove_cv_t<std::invoke_result_t<Func, U>>>;
#else #else
template <typename Func, typename U> // Keep ::type here because we still support C++11
using FunctionReturnType = typename std::remove_reference<typename std::remove_cv<typename std::result_of<Func(U)>::type>::type>::type; 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 #endif
} // namespace Catch } // namespace Catch

View File

@@ -66,7 +66,7 @@ namespace Catch {
if (tmpnam_s(m_buffer)) { if (tmpnam_s(m_buffer)) {
CATCH_RUNTIME_ERROR("Could not get a temp filename"); CATCH_RUNTIME_ERROR("Could not get a temp filename");
} }
if (fopen_s(&m_file, m_buffer, "w")) { if (fopen_s(&m_file, m_buffer, "w+")) {
char buffer[100]; char buffer[100];
if (strerror_s(buffer, errno)) { if (strerror_s(buffer, errno)) {
CATCH_RUNTIME_ERROR("Could not translate errno to a string"); CATCH_RUNTIME_ERROR("Could not translate errno to a string");

View File

@@ -9,13 +9,16 @@
#ifndef TWOBLUECUBES_CATCH_PLATFORM_H_INCLUDED #ifndef TWOBLUECUBES_CATCH_PLATFORM_H_INCLUDED
#define TWOBLUECUBES_CATCH_PLATFORM_H_INCLUDED #define TWOBLUECUBES_CATCH_PLATFORM_H_INCLUDED
// See e.g.:
// https://opensource.apple.com/source/CarbonHeaders/CarbonHeaders-18.1/TargetConditionals.h.auto.html
#ifdef __APPLE__ #ifdef __APPLE__
# include <TargetConditionals.h> # include <TargetConditionals.h>
# if TARGET_OS_OSX == 1 # if (defined(TARGET_OS_OSX) && TARGET_OS_OSX == 1) || \
# define CATCH_PLATFORM_MAC (defined(TARGET_OS_MAC) && TARGET_OS_MAC == 1)
# elif TARGET_OS_IPHONE == 1 # define CATCH_PLATFORM_MAC
# define CATCH_PLATFORM_IPHONE # elif (defined(TARGET_OS_IPHONE) && TARGET_OS_IPHONE == 1)
# endif # define CATCH_PLATFORM_IPHONE
# endif
#elif defined(linux) || defined(__linux) || defined(__linux__) #elif defined(linux) || defined(__linux) || defined(__linux__)
# define CATCH_PLATFORM_LINUX # define CATCH_PLATFORM_LINUX

View File

@@ -1,3 +1,4 @@
/* /*
* Created by Jozef on 12/11/2018. * Created by Jozef on 12/11/2018.
* Copyright 2017 Two Blue Cubes Ltd. All rights reserved. * Copyright 2017 Two Blue Cubes Ltd. All rights reserved.
@@ -90,7 +91,7 @@
#define INTERNAL_CATCH_REMOVE_PARENS_4_ARG(_0, _1, _2, _3) INTERNAL_CATCH_REMOVE_PARENS(_0), INTERNAL_CATCH_REMOVE_PARENS_3_ARG(_1, _2, _3) #define INTERNAL_CATCH_REMOVE_PARENS_4_ARG(_0, _1, _2, _3) INTERNAL_CATCH_REMOVE_PARENS(_0), INTERNAL_CATCH_REMOVE_PARENS_3_ARG(_1, _2, _3)
#define INTERNAL_CATCH_REMOVE_PARENS_5_ARG(_0, _1, _2, _3, _4) INTERNAL_CATCH_REMOVE_PARENS(_0), INTERNAL_CATCH_REMOVE_PARENS_4_ARG(_1, _2, _3, _4) #define INTERNAL_CATCH_REMOVE_PARENS_5_ARG(_0, _1, _2, _3, _4) INTERNAL_CATCH_REMOVE_PARENS(_0), INTERNAL_CATCH_REMOVE_PARENS_4_ARG(_1, _2, _3, _4)
#define INTERNAL_CATCH_REMOVE_PARENS_6_ARG(_0, _1, _2, _3, _4, _5) INTERNAL_CATCH_REMOVE_PARENS(_0), INTERNAL_CATCH_REMOVE_PARENS_5_ARG(_1, _2, _3, _4, _5) #define INTERNAL_CATCH_REMOVE_PARENS_6_ARG(_0, _1, _2, _3, _4, _5) INTERNAL_CATCH_REMOVE_PARENS(_0), INTERNAL_CATCH_REMOVE_PARENS_5_ARG(_1, _2, _3, _4, _5)
#define INTERNAL_CATCH_REMOVE_PARENS_7_ARG(_0, _1, _2, _3, _4, _5, _6) INTERNAL_CATCH_REMOVE_PARENS(_0), INTERNAL_CATCH_REMOVE_PARENS_6_ARG(_1, _2, _4, _5, _6) #define INTERNAL_CATCH_REMOVE_PARENS_7_ARG(_0, _1, _2, _3, _4, _5, _6) INTERNAL_CATCH_REMOVE_PARENS(_0), INTERNAL_CATCH_REMOVE_PARENS_6_ARG(_1, _2, _3, _4, _5, _6)
#define INTERNAL_CATCH_REMOVE_PARENS_8_ARG(_0, _1, _2, _3, _4, _5, _6, _7) INTERNAL_CATCH_REMOVE_PARENS(_0), INTERNAL_CATCH_REMOVE_PARENS_7_ARG(_1, _2, _3, _4, _5, _6, _7) #define INTERNAL_CATCH_REMOVE_PARENS_8_ARG(_0, _1, _2, _3, _4, _5, _6, _7) INTERNAL_CATCH_REMOVE_PARENS(_0), INTERNAL_CATCH_REMOVE_PARENS_7_ARG(_1, _2, _3, _4, _5, _6, _7)
#define INTERNAL_CATCH_REMOVE_PARENS_9_ARG(_0, _1, _2, _3, _4, _5, _6, _7, _8) INTERNAL_CATCH_REMOVE_PARENS(_0), INTERNAL_CATCH_REMOVE_PARENS_8_ARG(_1, _2, _3, _4, _5, _6, _7, _8) #define INTERNAL_CATCH_REMOVE_PARENS_9_ARG(_0, _1, _2, _3, _4, _5, _6, _7, _8) INTERNAL_CATCH_REMOVE_PARENS(_0), INTERNAL_CATCH_REMOVE_PARENS_8_ARG(_1, _2, _3, _4, _5, _6, _7, _8)
#define INTERNAL_CATCH_REMOVE_PARENS_10_ARG(_0, _1, _2, _3, _4, _5, _6, _7, _8, _9) INTERNAL_CATCH_REMOVE_PARENS(_0), INTERNAL_CATCH_REMOVE_PARENS_9_ARG(_1, _2, _3, _4, _5, _6, _7, _8, _9) #define INTERNAL_CATCH_REMOVE_PARENS_10_ARG(_0, _1, _2, _3, _4, _5, _6, _7, _8, _9) INTERNAL_CATCH_REMOVE_PARENS(_0), INTERNAL_CATCH_REMOVE_PARENS_9_ARG(_1, _2, _3, _4, _5, _6, _7, _8, _9)

View File

@@ -59,7 +59,11 @@ namespace Catch {
m_tagAliasRegistry.add( alias, tag, lineInfo ); m_tagAliasRegistry.add( alias, tag, lineInfo );
} }
void registerStartupException() noexcept override { void registerStartupException() noexcept override {
#if !defined(CATCH_CONFIG_DISABLE_EXCEPTIONS)
m_exceptionRegistry.add(std::current_exception()); m_exceptionRegistry.add(std::current_exception());
#else
CATCH_INTERNAL_ERROR("Attempted to register active exception under CATCH_CONFIG_DISABLE_EXCEPTIONS!");
#endif
} }
IMutableEnumValuesRegistry& getMutableEnumValuesRegistry() override { IMutableEnumValuesRegistry& getMutableEnumValuesRegistry() override {
return m_enumValuesRegistry; return m_enumValuesRegistry;

View File

@@ -25,17 +25,32 @@ namespace Catch {
std::shared_ptr<GeneratorTracker> tracker; std::shared_ptr<GeneratorTracker> tracker;
ITracker& currentTracker = ctx.currentTracker(); ITracker& currentTracker = ctx.currentTracker();
if( TestCaseTracking::ITrackerPtr childTracker = currentTracker.findChild( nameAndLocation ) ) { // Under specific circumstances, the generator we want
// to acquire is also the current tracker. If this is
// the case, we have to avoid looking through current
// tracker's children, and instead return the current
// tracker.
// A case where this check is important is e.g.
// for (int i = 0; i < 5; ++i) {
// int n = GENERATE(1, 2);
// }
//
// without it, the code above creates 5 nested generators.
if (currentTracker.nameAndLocation() == nameAndLocation) {
auto thisTracker = currentTracker.parent().findChild(nameAndLocation);
assert(thisTracker);
assert(thisTracker->isGeneratorTracker());
tracker = std::static_pointer_cast<GeneratorTracker>(thisTracker);
} else if ( TestCaseTracking::ITrackerPtr childTracker = currentTracker.findChild( nameAndLocation ) ) {
assert( childTracker ); assert( childTracker );
assert( childTracker->isGeneratorTracker() ); assert( childTracker->isGeneratorTracker() );
tracker = std::static_pointer_cast<GeneratorTracker>( childTracker ); tracker = std::static_pointer_cast<GeneratorTracker>( childTracker );
} } else {
else {
tracker = std::make_shared<GeneratorTracker>( nameAndLocation, ctx, &currentTracker ); tracker = std::make_shared<GeneratorTracker>( nameAndLocation, ctx, &currentTracker );
currentTracker.addChild( tracker ); currentTracker.addChild( tracker );
} }
if( !ctx.completedCycle() && !tracker->isComplete() ) { if( !tracker->isComplete() ) {
tracker->open(); tracker->open();
} }
@@ -49,8 +64,68 @@ namespace Catch {
} }
void close() override { void close() override {
TrackerBase::close(); TrackerBase::close();
// Generator interface only finds out if it has another item on atual move // If a generator has a child (it is followed by a section)
if (m_runState == CompletedSuccessfully && m_generator->next()) { // and none of its children have started, then we must wait
// until later to start consuming its values.
// This catches cases where `GENERATE` is placed between two
// `SECTION`s.
// **The check for m_children.empty cannot be removed**.
// doing so would break `GENERATE` _not_ followed by `SECTION`s.
const bool should_wait_for_child = [&]() {
// No children -> nobody to wait for
if ( m_children.empty() ) {
return false;
}
// If at least one child started executing, don't wait
if ( std::find_if(
m_children.begin(),
m_children.end(),
[]( TestCaseTracking::ITrackerPtr tracker ) {
return tracker->hasStarted();
} ) != m_children.end() ) {
return false;
}
// No children have started. We need to check if they _can_
// start, and thus we should wait for them, or they cannot
// start (due to filters), and we shouldn't wait for them
auto* parent = m_parent;
// This is safe: there is always at least one section
// tracker in a test case tracking tree
while ( !parent->isSectionTracker() ) {
parent = &( parent->parent() );
}
assert( parent &&
"Missing root (test case) level section" );
auto const& parentSection =
static_cast<SectionTracker&>( *parent );
auto const& filters = parentSection.getFilters();
// No filters -> no restrictions on running sections
if ( filters.empty() ) {
return true;
}
for ( auto const& child : m_children ) {
if ( child->isSectionTracker() &&
std::find( filters.begin(),
filters.end(),
static_cast<SectionTracker&>( *child )
.trimmedName() ) !=
filters.end() ) {
return true;
}
}
return false;
}();
// This check is a bit tricky, because m_generator->next()
// has a side-effect, where it consumes generator's current
// value, but we do not want to invoke the side-effect if
// this generator is still waiting for any child to start.
if ( should_wait_for_child ||
( m_runState == CompletedSuccessfully &&
m_generator->next() ) ) {
m_children.clear(); m_children.clear();
m_runState = Executing; m_runState = Executing;
} }
@@ -187,10 +262,10 @@ namespace Catch {
return true; return true;
} }
auto RunContext::acquireGeneratorTracker( SourceLineInfo const& lineInfo ) -> IGeneratorTracker& { auto RunContext::acquireGeneratorTracker( StringRef generatorName, SourceLineInfo const& lineInfo ) -> IGeneratorTracker& {
using namespace Generators; using namespace Generators;
GeneratorTracker& tracker = GeneratorTracker::acquire( m_trackerContext, TestCaseTracking::NameAndLocation( "generator", lineInfo ) ); GeneratorTracker& tracker = GeneratorTracker::acquire(m_trackerContext,
assert( tracker.isOpen() ); TestCaseTracking::NameAndLocation( static_cast<std::string>(generatorName), lineInfo ) );
m_lastAssertionInfo.lineInfo = lineInfo; m_lastAssertionInfo.lineInfo = lineInfo;
return tracker; return tracker;
} }
@@ -233,17 +308,17 @@ namespace Catch {
#if defined(CATCH_CONFIG_ENABLE_BENCHMARKING) #if defined(CATCH_CONFIG_ENABLE_BENCHMARKING)
void RunContext::benchmarkPreparing(std::string const& name) { void RunContext::benchmarkPreparing(std::string const& name) {
m_reporter->benchmarkPreparing(name); m_reporter->benchmarkPreparing(name);
} }
void RunContext::benchmarkStarting( BenchmarkInfo const& info ) { void RunContext::benchmarkStarting( BenchmarkInfo const& info ) {
m_reporter->benchmarkStarting( info ); m_reporter->benchmarkStarting( info );
} }
void RunContext::benchmarkEnded( BenchmarkStats<> const& stats ) { void RunContext::benchmarkEnded( BenchmarkStats<> const& stats ) {
m_reporter->benchmarkEnded( stats ); m_reporter->benchmarkEnded( stats );
} }
void RunContext::benchmarkFailed(std::string const & error) { void RunContext::benchmarkFailed(std::string const & error) {
m_reporter->benchmarkFailed(error); m_reporter->benchmarkFailed(error);
} }
#endif // CATCH_CONFIG_ENABLE_BENCHMARKING #endif // CATCH_CONFIG_ENABLE_BENCHMARKING
void RunContext::pushScopedMessage(MessageInfo const & message) { void RunContext::pushScopedMessage(MessageInfo const & message) {
@@ -377,9 +452,8 @@ namespace Catch {
} }
void RunContext::invokeActiveTestCase() { void RunContext::invokeActiveTestCase() {
FatalConditionHandler fatalConditionHandler; // Handle signals FatalConditionHandlerGuard _(&m_fatalConditionhandler);
m_activeTestCase->invoke(); m_activeTestCase->invoke();
fatalConditionHandler.reset();
} }
void RunContext::handleUnfinishedSections() { void RunContext::handleUnfinishedSections() {

View File

@@ -80,7 +80,7 @@ namespace Catch {
void sectionEnded( SectionEndInfo const& endInfo ) override; void sectionEnded( SectionEndInfo const& endInfo ) override;
void sectionEndedEarly( SectionEndInfo const& endInfo ) override; void sectionEndedEarly( SectionEndInfo const& endInfo ) override;
auto acquireGeneratorTracker( SourceLineInfo const& lineInfo ) -> IGeneratorTracker& override; auto acquireGeneratorTracker( StringRef generatorName, SourceLineInfo const& lineInfo ) -> IGeneratorTracker& override;
#if defined(CATCH_CONFIG_ENABLE_BENCHMARKING) #if defined(CATCH_CONFIG_ENABLE_BENCHMARKING)
void benchmarkPreparing( std::string const& name ) override; void benchmarkPreparing( std::string const& name ) override;
@@ -146,6 +146,7 @@ namespace Catch {
std::vector<SectionEndInfo> m_unfinishedSections; std::vector<SectionEndInfo> m_unfinishedSections;
std::vector<ITracker*> m_activeSections; std::vector<ITracker*> m_activeSections;
TrackerContext m_trackerContext; TrackerContext m_trackerContext;
FatalConditionHandler m_fatalConditionhandler;
bool m_lastAssertionPassed = false; bool m_lastAssertionPassed = false;
bool m_shouldReportUnexpected = true; bool m_shouldReportUnexpected = true;
bool m_includeSuccessfulResults; bool m_includeSuccessfulResults;

View File

@@ -9,6 +9,7 @@
#include "catch_startup_exception_registry.h" #include "catch_startup_exception_registry.h"
#include "catch_compiler_capabilities.h" #include "catch_compiler_capabilities.h"
#if !defined(CATCH_CONFIG_DISABLE_EXCEPTIONS)
namespace Catch { namespace Catch {
void StartupExceptionRegistry::add( std::exception_ptr const& exception ) noexcept { void StartupExceptionRegistry::add( std::exception_ptr const& exception ) noexcept {
CATCH_TRY { CATCH_TRY {
@@ -24,3 +25,4 @@ void StartupExceptionRegistry::add( std::exception_ptr const& exception ) noexce
} }
} // end namespace Catch } // end namespace Catch
#endif

View File

@@ -15,11 +15,13 @@
namespace Catch { namespace Catch {
class StartupExceptionRegistry { class StartupExceptionRegistry {
#if !defined(CATCH_CONFIG_DISABLE_EXCEPTIONS)
public: public:
void add(std::exception_ptr const& exception) noexcept; void add(std::exception_ptr const& exception) noexcept;
std::vector<std::exception_ptr> const& getExceptions() const noexcept; std::vector<std::exception_ptr> const& getExceptions() const noexcept;
private: private:
std::vector<std::exception_ptr> m_exceptions; std::vector<std::exception_ptr> m_exceptions;
#endif
}; };
} // end namespace Catch } // end namespace Catch

View File

@@ -18,7 +18,7 @@ namespace Catch {
namespace { namespace {
char toLowerCh(char c) { char toLowerCh(char c) {
return static_cast<char>( std::tolower( c ) ); return static_cast<char>( std::tolower( static_cast<unsigned char>(c) ) );
} }
} }

View File

@@ -15,27 +15,82 @@
#include "catch_string_manip.h" #include "catch_string_manip.h"
#include "catch_test_case_info.h" #include "catch_test_case_info.h"
#include <algorithm>
#include <sstream> #include <sstream>
namespace Catch { namespace Catch {
namespace {
struct TestHasher {
using hash_t = uint64_t;
explicit TestHasher( hash_t hashSuffix ):
m_hashSuffix{ hashSuffix } {}
uint32_t operator()( TestCase const& t ) const {
// FNV-1a hash with multiplication fold.
const hash_t prime = 1099511628211u;
hash_t hash = 14695981039346656037u;
for ( const char c : t.name ) {
hash ^= c;
hash *= prime;
}
hash ^= m_hashSuffix;
hash *= prime;
const uint32_t low{ static_cast<uint32_t>( hash ) };
const uint32_t high{ static_cast<uint32_t>( hash >> 32 ) };
return low * high;
}
private:
hash_t m_hashSuffix;
};
} // end unnamed namespace
std::vector<TestCase> sortTests( IConfig const& config, std::vector<TestCase> const& unsortedTestCases ) { std::vector<TestCase> sortTests( IConfig const& config, std::vector<TestCase> const& unsortedTestCases ) {
std::vector<TestCase> sorted = unsortedTestCases;
switch( config.runOrder() ) { switch( config.runOrder() ) {
case RunTests::InLexicographicalOrder:
std::sort( sorted.begin(), sorted.end() );
break;
case RunTests::InRandomOrder:
seedRng( config );
std::shuffle( sorted.begin(), sorted.end(), rng() );
break;
case RunTests::InDeclarationOrder: case RunTests::InDeclarationOrder:
// already in declaration order // already in declaration order
break; break;
case RunTests::InLexicographicalOrder: {
std::vector<TestCase> sorted = unsortedTestCases;
std::sort( sorted.begin(), sorted.end() );
return sorted;
}
case RunTests::InRandomOrder: {
seedRng( config );
TestHasher h{ config.rngSeed() };
using hashedTest = std::pair<TestHasher::hash_t, TestCase const*>;
std::vector<hashedTest> indexed_tests;
indexed_tests.reserve( unsortedTestCases.size() );
for (auto const& testCase : unsortedTestCases) {
indexed_tests.emplace_back(h(testCase), &testCase);
}
std::sort(indexed_tests.begin(), indexed_tests.end(),
[](hashedTest const& lhs, hashedTest const& rhs) {
if (lhs.first == rhs.first) {
return lhs.second->name < rhs.second->name;
}
return lhs.first < rhs.first;
});
std::vector<TestCase> sorted;
sorted.reserve( indexed_tests.size() );
for (auto const& hashed : indexed_tests) {
sorted.emplace_back(*hashed.second);
}
return sorted;
}
} }
return sorted; return unsortedTestCases;
} }
bool isThrowSafe( TestCase const& testCase, IConfig const& config ) { bool isThrowSafe( TestCase const& testCase, IConfig const& config ) {

View File

@@ -65,15 +65,12 @@ namespace TestCaseTracking {
} }
TrackerBase::TrackerBase( NameAndLocation const& nameAndLocation, TrackerContext& ctx, ITracker* parent ) TrackerBase::TrackerBase( NameAndLocation const& nameAndLocation, TrackerContext& ctx, ITracker* parent ):
: m_nameAndLocation( nameAndLocation ), ITracker(nameAndLocation),
m_ctx( ctx ), m_ctx( ctx ),
m_parent( parent ) m_parent( parent )
{} {}
NameAndLocation const& TrackerBase::nameAndLocation() const {
return m_nameAndLocation;
}
bool TrackerBase::isComplete() const { bool TrackerBase::isComplete() const {
return m_runState == CompletedSuccessfully || m_runState == Failed; return m_runState == CompletedSuccessfully || m_runState == Failed;
} }
@@ -190,7 +187,8 @@ namespace TestCaseTracking {
bool SectionTracker::isComplete() const { bool SectionTracker::isComplete() const {
bool complete = true; bool complete = true;
if ((m_filters.empty() || m_filters[0] == "") if (m_filters.empty()
|| m_filters[0] == ""
|| std::find(m_filters.begin(), m_filters.end(), m_trimmed_name) != m_filters.end()) { || std::find(m_filters.begin(), m_filters.end(), m_trimmed_name) != m_filters.end()) {
complete = TrackerBase::isComplete(); complete = TrackerBase::isComplete();
} }
@@ -235,6 +233,14 @@ namespace TestCaseTracking {
m_filters.insert( m_filters.end(), filters.begin()+1, filters.end() ); m_filters.insert( m_filters.end(), filters.begin()+1, filters.end() );
} }
std::vector<std::string> const& SectionTracker::getFilters() const {
return m_filters;
}
std::string const& SectionTracker::trimmedName() const {
return m_trimmed_name;
}
} // namespace TestCaseTracking } // namespace TestCaseTracking
using TestCaseTracking::ITracker; using TestCaseTracking::ITracker;

View File

@@ -23,23 +23,39 @@ namespace TestCaseTracking {
SourceLineInfo location; SourceLineInfo location;
NameAndLocation( std::string const& _name, SourceLineInfo const& _location ); NameAndLocation( std::string const& _name, SourceLineInfo const& _location );
friend bool operator==(NameAndLocation const& lhs, NameAndLocation const& rhs) {
return lhs.name == rhs.name
&& lhs.location == rhs.location;
}
}; };
struct ITracker; class ITracker;
using ITrackerPtr = std::shared_ptr<ITracker>; using ITrackerPtr = std::shared_ptr<ITracker>;
struct ITracker { class ITracker {
virtual ~ITracker(); NameAndLocation m_nameAndLocation;
public:
ITracker(NameAndLocation const& nameAndLoc) :
m_nameAndLocation(nameAndLoc)
{}
// static queries // static queries
virtual NameAndLocation const& nameAndLocation() const = 0; NameAndLocation const& nameAndLocation() const {
return m_nameAndLocation;
}
virtual ~ITracker();
// dynamic queries // dynamic queries
virtual bool isComplete() const = 0; // Successfully completed or failed virtual bool isComplete() const = 0; // Successfully completed or failed
virtual bool isSuccessfullyCompleted() const = 0; virtual bool isSuccessfullyCompleted() const = 0;
virtual bool isOpen() const = 0; // Started but not complete virtual bool isOpen() const = 0; // Started but not complete
virtual bool hasChildren() const = 0; virtual bool hasChildren() const = 0;
virtual bool hasStarted() const = 0;
virtual ITracker& parent() = 0; virtual ITracker& parent() = 0;
@@ -94,7 +110,6 @@ namespace TestCaseTracking {
}; };
using Children = std::vector<ITrackerPtr>; using Children = std::vector<ITrackerPtr>;
NameAndLocation m_nameAndLocation;
TrackerContext& m_ctx; TrackerContext& m_ctx;
ITracker* m_parent; ITracker* m_parent;
Children m_children; Children m_children;
@@ -103,12 +118,13 @@ namespace TestCaseTracking {
public: public:
TrackerBase( NameAndLocation const& nameAndLocation, TrackerContext& ctx, ITracker* parent ); TrackerBase( NameAndLocation const& nameAndLocation, TrackerContext& ctx, ITracker* parent );
NameAndLocation const& nameAndLocation() const override;
bool isComplete() const override; bool isComplete() const override;
bool isSuccessfullyCompleted() const override; bool isSuccessfullyCompleted() const override;
bool isOpen() const override; bool isOpen() const override;
bool hasChildren() const override; bool hasChildren() const override;
bool hasStarted() const override {
return m_runState != NotStarted;
}
void addChild( ITrackerPtr const& child ) override; void addChild( ITrackerPtr const& child ) override;
@@ -147,6 +163,10 @@ namespace TestCaseTracking {
void addInitialFilters( std::vector<std::string> const& filters ); void addInitialFilters( std::vector<std::string> const& filters );
void addNextFilters( std::vector<std::string> const& filters ); void addNextFilters( std::vector<std::string> const& filters );
//! Returns filters active in this tracker
std::vector<std::string> const& getFilters() const;
//! Returns whitespace-trimmed name of the tracked section
std::string const& trimmedName() const;
}; };
} // namespace TestCaseTracking } // namespace TestCaseTracking

View File

@@ -71,34 +71,34 @@ struct AutoReg : NonCopyable {
#ifndef CATCH_CONFIG_TRADITIONAL_MSVC_PREPROCESSOR #ifndef CATCH_CONFIG_TRADITIONAL_MSVC_PREPROCESSOR
#define INTERNAL_CATCH_TEMPLATE_TEST_CASE_NO_REGISTRATION(Name, Tags, ...) \ #define INTERNAL_CATCH_TEMPLATE_TEST_CASE_NO_REGISTRATION(Name, Tags, ...) \
INTERNAL_CATCH_TEMPLATE_TEST_CASE_NO_REGISTRATION_2( INTERNAL_CATCH_UNIQUE_NAME( ____C_A_T_C_H____T_E_M_P_L_A_T_E____T_E_S_T____ ), INTERNAL_CATCH_UNIQUE_NAME( ____C_A_T_C_H____T_E_M_P_L_A_T_E____T_E_S_T____F_U_N_C____ ), Name, Tags, typename TestType, __VA_ARGS__ ) INTERNAL_CATCH_TEMPLATE_TEST_CASE_NO_REGISTRATION_2( INTERNAL_CATCH_UNIQUE_NAME( C_A_T_C_H_T_E_M_P_L_A_T_E_T_E_S_T_ ), INTERNAL_CATCH_UNIQUE_NAME( C_A_T_C_H_T_E_M_P_L_A_T_E_T_E_S_T_F_U_N_C_ ), Name, Tags, typename TestType, __VA_ARGS__ )
#else #else
#define INTERNAL_CATCH_TEMPLATE_TEST_CASE_NO_REGISTRATION(Name, Tags, ...) \ #define INTERNAL_CATCH_TEMPLATE_TEST_CASE_NO_REGISTRATION(Name, Tags, ...) \
INTERNAL_CATCH_EXPAND_VARGS( INTERNAL_CATCH_TEMPLATE_TEST_CASE_NO_REGISTRATION_2( INTERNAL_CATCH_UNIQUE_NAME( ____C_A_T_C_H____T_E_M_P_L_A_T_E____T_E_S_T____ ), INTERNAL_CATCH_UNIQUE_NAME( ____C_A_T_C_H____T_E_M_P_L_A_T_E____T_E_S_T____F_U_N_C____ ), Name, Tags, typename TestType, __VA_ARGS__ ) ) INTERNAL_CATCH_EXPAND_VARGS( INTERNAL_CATCH_TEMPLATE_TEST_CASE_NO_REGISTRATION_2( INTERNAL_CATCH_UNIQUE_NAME( C_A_T_C_H_T_E_M_P_L_A_T_E_T_E_S_T_ ), INTERNAL_CATCH_UNIQUE_NAME( C_A_T_C_H_T_E_M_P_L_A_T_E_T_E_S_T_F_U_N_C_ ), Name, Tags, typename TestType, __VA_ARGS__ ) )
#endif #endif
#ifndef CATCH_CONFIG_TRADITIONAL_MSVC_PREPROCESSOR #ifndef CATCH_CONFIG_TRADITIONAL_MSVC_PREPROCESSOR
#define INTERNAL_CATCH_TEMPLATE_TEST_CASE_SIG_NO_REGISTRATION(Name, Tags, Signature, ...) \ #define INTERNAL_CATCH_TEMPLATE_TEST_CASE_SIG_NO_REGISTRATION(Name, Tags, Signature, ...) \
INTERNAL_CATCH_TEMPLATE_TEST_CASE_NO_REGISTRATION_2( INTERNAL_CATCH_UNIQUE_NAME( ____C_A_T_C_H____T_E_M_P_L_A_T_E____T_E_S_T____ ), INTERNAL_CATCH_UNIQUE_NAME( ____C_A_T_C_H____T_E_M_P_L_A_T_E____T_E_S_T____F_U_N_C____ ), Name, Tags, Signature, __VA_ARGS__ ) INTERNAL_CATCH_TEMPLATE_TEST_CASE_NO_REGISTRATION_2( INTERNAL_CATCH_UNIQUE_NAME( C_A_T_C_H_T_E_M_P_L_A_T_E_T_E_S_T_ ), INTERNAL_CATCH_UNIQUE_NAME( C_A_T_C_H_T_E_M_P_L_A_T_E_T_E_S_T_F_U_N_C_ ), Name, Tags, Signature, __VA_ARGS__ )
#else #else
#define INTERNAL_CATCH_TEMPLATE_TEST_CASE_SIG_NO_REGISTRATION(Name, Tags, Signature, ...) \ #define INTERNAL_CATCH_TEMPLATE_TEST_CASE_SIG_NO_REGISTRATION(Name, Tags, Signature, ...) \
INTERNAL_CATCH_EXPAND_VARGS( INTERNAL_CATCH_TEMPLATE_TEST_CASE_NO_REGISTRATION_2( INTERNAL_CATCH_UNIQUE_NAME( ____C_A_T_C_H____T_E_M_P_L_A_T_E____T_E_S_T____ ), INTERNAL_CATCH_UNIQUE_NAME( ____C_A_T_C_H____T_E_M_P_L_A_T_E____T_E_S_T____F_U_N_C____ ), Name, Tags, Signature, __VA_ARGS__ ) ) INTERNAL_CATCH_EXPAND_VARGS( INTERNAL_CATCH_TEMPLATE_TEST_CASE_NO_REGISTRATION_2( INTERNAL_CATCH_UNIQUE_NAME( C_A_T_C_H_T_E_M_P_L_A_T_E_T_E_S_T_ ), INTERNAL_CATCH_UNIQUE_NAME( C_A_T_C_H_T_E_M_P_L_A_T_E_T_E_S_T_F_U_N_C_ ), Name, Tags, Signature, __VA_ARGS__ ) )
#endif #endif
#ifndef CATCH_CONFIG_TRADITIONAL_MSVC_PREPROCESSOR #ifndef CATCH_CONFIG_TRADITIONAL_MSVC_PREPROCESSOR
#define INTERNAL_CATCH_TEMPLATE_TEST_CASE_METHOD_NO_REGISTRATION( ClassName, Name, Tags,... ) \ #define INTERNAL_CATCH_TEMPLATE_TEST_CASE_METHOD_NO_REGISTRATION( ClassName, Name, Tags,... ) \
INTERNAL_CATCH_TEMPLATE_TEST_CASE_METHOD_NO_REGISTRATION_2( INTERNAL_CATCH_UNIQUE_NAME( ____C_A_T_C_H____T_E_M_P_L_A_T_E____T_E_S_T____C_L_A_S_S____ ), INTERNAL_CATCH_UNIQUE_NAME( ____C_A_T_C_H____T_E_M_P_L_A_T_E____T_E_S_T____ ) , ClassName, Name, Tags, typename T, __VA_ARGS__ ) INTERNAL_CATCH_TEMPLATE_TEST_CASE_METHOD_NO_REGISTRATION_2( INTERNAL_CATCH_UNIQUE_NAME( C_A_T_C_H_T_E_M_P_L_A_T_E_T_E_S_T_C_L_A_S_S_ ), INTERNAL_CATCH_UNIQUE_NAME( C_A_T_C_H_T_E_M_P_L_A_T_E_T_E_S_T_ ) , ClassName, Name, Tags, typename T, __VA_ARGS__ )
#else #else
#define INTERNAL_CATCH_TEMPLATE_TEST_CASE_METHOD_NO_REGISTRATION( ClassName, Name, Tags,... ) \ #define INTERNAL_CATCH_TEMPLATE_TEST_CASE_METHOD_NO_REGISTRATION( ClassName, Name, Tags,... ) \
INTERNAL_CATCH_EXPAND_VARGS( INTERNAL_CATCH_TEMPLATE_TEST_CASE_METHOD_NO_REGISTRATION_2( INTERNAL_CATCH_UNIQUE_NAME( ____C_A_T_C_H____T_E_M_P_L_A_T_E____T_E_S_T____C_L_A_S_S____ ), INTERNAL_CATCH_UNIQUE_NAME( ____C_A_T_C_H____T_E_M_P_L_A_T_E____T_E_S_T____ ) , ClassName, Name, Tags, typename T, __VA_ARGS__ ) ) INTERNAL_CATCH_EXPAND_VARGS( INTERNAL_CATCH_TEMPLATE_TEST_CASE_METHOD_NO_REGISTRATION_2( INTERNAL_CATCH_UNIQUE_NAME( C_A_T_C_H_T_E_M_P_L_A_T_E_T_E_S_T_C_L_A_S_S_ ), INTERNAL_CATCH_UNIQUE_NAME( C_A_T_C_H_T_E_M_P_L_A_T_E_T_E_S_T_ ) , ClassName, Name, Tags, typename T, __VA_ARGS__ ) )
#endif #endif
#ifndef CATCH_CONFIG_TRADITIONAL_MSVC_PREPROCESSOR #ifndef CATCH_CONFIG_TRADITIONAL_MSVC_PREPROCESSOR
#define INTERNAL_CATCH_TEMPLATE_TEST_CASE_METHOD_SIG_NO_REGISTRATION( ClassName, Name, Tags, Signature, ... ) \ #define INTERNAL_CATCH_TEMPLATE_TEST_CASE_METHOD_SIG_NO_REGISTRATION( ClassName, Name, Tags, Signature, ... ) \
INTERNAL_CATCH_TEMPLATE_TEST_CASE_METHOD_NO_REGISTRATION_2( INTERNAL_CATCH_UNIQUE_NAME( ____C_A_T_C_H____T_E_M_P_L_A_T_E____T_E_S_T____C_L_A_S_S____ ), INTERNAL_CATCH_UNIQUE_NAME( ____C_A_T_C_H____T_E_M_P_L_A_T_E____T_E_S_T____ ) , ClassName, Name, Tags, Signature, __VA_ARGS__ ) INTERNAL_CATCH_TEMPLATE_TEST_CASE_METHOD_NO_REGISTRATION_2( INTERNAL_CATCH_UNIQUE_NAME( C_A_T_C_H_T_E_M_P_L_A_T_E_T_E_S_T_C_L_A_S_S_ ), INTERNAL_CATCH_UNIQUE_NAME( C_A_T_C_H_T_E_M_P_L_A_T_E_T_E_S_T_ ) , ClassName, Name, Tags, Signature, __VA_ARGS__ )
#else #else
#define INTERNAL_CATCH_TEMPLATE_TEST_CASE_METHOD_SIG_NO_REGISTRATION( ClassName, Name, Tags, Signature, ... ) \ #define INTERNAL_CATCH_TEMPLATE_TEST_CASE_METHOD_SIG_NO_REGISTRATION( ClassName, Name, Tags, Signature, ... ) \
INTERNAL_CATCH_EXPAND_VARGS( INTERNAL_CATCH_TEMPLATE_TEST_CASE_METHOD_NO_REGISTRATION_2( INTERNAL_CATCH_UNIQUE_NAME( ____C_A_T_C_H____T_E_M_P_L_A_T_E____T_E_S_T____C_L_A_S_S____ ), INTERNAL_CATCH_UNIQUE_NAME( ____C_A_T_C_H____T_E_M_P_L_A_T_E____T_E_S_T____ ) , ClassName, Name, Tags, Signature, __VA_ARGS__ ) ) INTERNAL_CATCH_EXPAND_VARGS( INTERNAL_CATCH_TEMPLATE_TEST_CASE_METHOD_NO_REGISTRATION_2( INTERNAL_CATCH_UNIQUE_NAME( C_A_T_C_H_T_E_M_P_L_A_T_E_T_E_S_T_C_L_A_S_S_ ), INTERNAL_CATCH_UNIQUE_NAME( C_A_T_C_H_T_E_M_P_L_A_T_E_T_E_S_T_ ) , ClassName, Name, Tags, Signature, __VA_ARGS__ ) )
#endif #endif
#endif #endif
@@ -111,7 +111,7 @@ struct AutoReg : NonCopyable {
CATCH_INTERNAL_STOP_WARNINGS_SUPPRESSION \ 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, ... ) \
@@ -133,7 +133,7 @@ struct AutoReg : NonCopyable {
CATCH_INTERNAL_STOP_WARNINGS_SUPPRESSION \ 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, ... ) \
@@ -160,7 +160,7 @@ struct AutoReg : NonCopyable {
int index = 0; \ int index = 0; \
constexpr char const* tmpl_types[] = {CATCH_REC_LIST(INTERNAL_CATCH_STRINGIZE_WITHOUT_PARENS, __VA_ARGS__)};\ constexpr char const* tmpl_types[] = {CATCH_REC_LIST(INTERNAL_CATCH_STRINGIZE_WITHOUT_PARENS, __VA_ARGS__)};\
using expander = int[];\ using expander = int[];\
(void)expander{(reg_test(Types{}, Catch::NameAndTags{ Name " - " + std::string(tmpl_types[index]), Tags } ), index++, 0)... };/* NOLINT */ \ (void)expander{(reg_test(Types{}, Catch::NameAndTags{ Name " - " + std::string(tmpl_types[index]), Tags } ), index++)... };/* NOLINT */ \
}\ }\
};\ };\
static int INTERNAL_CATCH_UNIQUE_NAME( globalRegistrar ) = [](){\ static int INTERNAL_CATCH_UNIQUE_NAME( globalRegistrar ) = [](){\
@@ -174,18 +174,18 @@ struct AutoReg : NonCopyable {
#ifndef CATCH_CONFIG_TRADITIONAL_MSVC_PREPROCESSOR #ifndef CATCH_CONFIG_TRADITIONAL_MSVC_PREPROCESSOR
#define INTERNAL_CATCH_TEMPLATE_TEST_CASE(Name, Tags, ...) \ #define INTERNAL_CATCH_TEMPLATE_TEST_CASE(Name, Tags, ...) \
INTERNAL_CATCH_TEMPLATE_TEST_CASE_2( INTERNAL_CATCH_UNIQUE_NAME( ____C_A_T_C_H____T_E_M_P_L_A_T_E____T_E_S_T____ ), INTERNAL_CATCH_UNIQUE_NAME( ____C_A_T_C_H____T_E_M_P_L_A_T_E____T_E_S_T____F_U_N_C____ ), Name, Tags, typename TestType, __VA_ARGS__ ) INTERNAL_CATCH_TEMPLATE_TEST_CASE_2( INTERNAL_CATCH_UNIQUE_NAME( C_A_T_C_H_T_E_M_P_L_A_T_E_T_E_S_T_ ), INTERNAL_CATCH_UNIQUE_NAME( C_A_T_C_H_T_E_M_P_L_A_T_E_T_E_S_T_F_U_N_C_ ), Name, Tags, typename TestType, __VA_ARGS__ )
#else #else
#define INTERNAL_CATCH_TEMPLATE_TEST_CASE(Name, Tags, ...) \ #define INTERNAL_CATCH_TEMPLATE_TEST_CASE(Name, Tags, ...) \
INTERNAL_CATCH_EXPAND_VARGS( INTERNAL_CATCH_TEMPLATE_TEST_CASE_2( INTERNAL_CATCH_UNIQUE_NAME( ____C_A_T_C_H____T_E_M_P_L_A_T_E____T_E_S_T____ ), INTERNAL_CATCH_UNIQUE_NAME( ____C_A_T_C_H____T_E_M_P_L_A_T_E____T_E_S_T____F_U_N_C____ ), Name, Tags, typename TestType, __VA_ARGS__ ) ) INTERNAL_CATCH_EXPAND_VARGS( INTERNAL_CATCH_TEMPLATE_TEST_CASE_2( INTERNAL_CATCH_UNIQUE_NAME( C_A_T_C_H_T_E_M_P_L_A_T_E_T_E_S_T_ ), INTERNAL_CATCH_UNIQUE_NAME( C_A_T_C_H_T_E_M_P_L_A_T_E_T_E_S_T_F_U_N_C_ ), Name, Tags, typename TestType, __VA_ARGS__ ) )
#endif #endif
#ifndef CATCH_CONFIG_TRADITIONAL_MSVC_PREPROCESSOR #ifndef CATCH_CONFIG_TRADITIONAL_MSVC_PREPROCESSOR
#define INTERNAL_CATCH_TEMPLATE_TEST_CASE_SIG(Name, Tags, Signature, ...) \ #define INTERNAL_CATCH_TEMPLATE_TEST_CASE_SIG(Name, Tags, Signature, ...) \
INTERNAL_CATCH_TEMPLATE_TEST_CASE_2( INTERNAL_CATCH_UNIQUE_NAME( ____C_A_T_C_H____T_E_M_P_L_A_T_E____T_E_S_T____ ), INTERNAL_CATCH_UNIQUE_NAME( ____C_A_T_C_H____T_E_M_P_L_A_T_E____T_E_S_T____F_U_N_C____ ), Name, Tags, Signature, __VA_ARGS__ ) INTERNAL_CATCH_TEMPLATE_TEST_CASE_2( INTERNAL_CATCH_UNIQUE_NAME( C_A_T_C_H_T_E_M_P_L_A_T_E_T_E_S_T_ ), INTERNAL_CATCH_UNIQUE_NAME( C_A_T_C_H_T_E_M_P_L_A_T_E_T_E_S_T_F_U_N_C_ ), Name, Tags, Signature, __VA_ARGS__ )
#else #else
#define INTERNAL_CATCH_TEMPLATE_TEST_CASE_SIG(Name, Tags, Signature, ...) \ #define INTERNAL_CATCH_TEMPLATE_TEST_CASE_SIG(Name, Tags, Signature, ...) \
INTERNAL_CATCH_EXPAND_VARGS( INTERNAL_CATCH_TEMPLATE_TEST_CASE_2( INTERNAL_CATCH_UNIQUE_NAME( ____C_A_T_C_H____T_E_M_P_L_A_T_E____T_E_S_T____ ), INTERNAL_CATCH_UNIQUE_NAME( ____C_A_T_C_H____T_E_M_P_L_A_T_E____T_E_S_T____F_U_N_C____ ), Name, Tags, Signature, __VA_ARGS__ ) ) INTERNAL_CATCH_EXPAND_VARGS( INTERNAL_CATCH_TEMPLATE_TEST_CASE_2( INTERNAL_CATCH_UNIQUE_NAME( C_A_T_C_H_T_E_M_P_L_A_T_E_T_E_S_T_ ), INTERNAL_CATCH_UNIQUE_NAME( C_A_T_C_H_T_E_M_P_L_A_T_E_T_E_S_T_F_U_N_C_ ), Name, Tags, Signature, __VA_ARGS__ ) )
#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) \
@@ -206,7 +206,7 @@ struct AutoReg : NonCopyable {
constexpr char const* tmpl_types[] = {CATCH_REC_LIST(INTERNAL_CATCH_STRINGIZE_WITHOUT_PARENS, INTERNAL_CATCH_REMOVE_PARENS(TmplTypes))};\ constexpr char const* tmpl_types[] = {CATCH_REC_LIST(INTERNAL_CATCH_STRINGIZE_WITHOUT_PARENS, INTERNAL_CATCH_REMOVE_PARENS(TmplTypes))};\
constexpr char const* types_list[] = {CATCH_REC_LIST(INTERNAL_CATCH_STRINGIZE_WITHOUT_PARENS, INTERNAL_CATCH_REMOVE_PARENS(TypesList))};\ constexpr char const* types_list[] = {CATCH_REC_LIST(INTERNAL_CATCH_STRINGIZE_WITHOUT_PARENS, INTERNAL_CATCH_REMOVE_PARENS(TypesList))};\
constexpr auto num_types = sizeof(types_list) / sizeof(types_list[0]);\ constexpr auto num_types = sizeof(types_list) / sizeof(types_list[0]);\
(void)expander{(Catch::AutoReg( Catch::makeTestInvoker( &TestFuncName<Types> ), CATCH_INTERNAL_LINEINFO, Catch::StringRef(), Catch::NameAndTags{ Name " - " + std::string(tmpl_types[index / num_types]) + "<" + std::string(types_list[index % num_types]) + ">", Tags } ), index++, 0)... };/* NOLINT */\ (void)expander{(Catch::AutoReg( Catch::makeTestInvoker( &TestFuncName<Types> ), CATCH_INTERNAL_LINEINFO, Catch::StringRef(), Catch::NameAndTags{ Name " - " + std::string(tmpl_types[index / num_types]) + "<" + std::string(types_list[index % num_types]) + ">", Tags } ), index++)... };/* NOLINT */\
} \ } \
}; \ }; \
static int INTERNAL_CATCH_UNIQUE_NAME( globalRegistrar ) = [](){ \ static int INTERNAL_CATCH_UNIQUE_NAME( globalRegistrar ) = [](){ \
@@ -223,18 +223,18 @@ struct AutoReg : NonCopyable {
#ifndef CATCH_CONFIG_TRADITIONAL_MSVC_PREPROCESSOR #ifndef CATCH_CONFIG_TRADITIONAL_MSVC_PREPROCESSOR
#define INTERNAL_CATCH_TEMPLATE_PRODUCT_TEST_CASE(Name, Tags, ...)\ #define INTERNAL_CATCH_TEMPLATE_PRODUCT_TEST_CASE(Name, Tags, ...)\
INTERNAL_CATCH_TEMPLATE_PRODUCT_TEST_CASE2(INTERNAL_CATCH_UNIQUE_NAME( ____C_A_T_C_H____T_E_M_P_L_A_T_E____T_E_S_T____ ), INTERNAL_CATCH_UNIQUE_NAME( ____C_A_T_C_H____T_E_M_P_L_A_T_E____T_E_S_T____F_U_N_C____ ), Name, Tags, typename T,__VA_ARGS__) INTERNAL_CATCH_TEMPLATE_PRODUCT_TEST_CASE2(INTERNAL_CATCH_UNIQUE_NAME( C_A_T_C_H_T_E_M_P_L_A_T_E_T_E_S_T_ ), INTERNAL_CATCH_UNIQUE_NAME( C_A_T_C_H_T_E_M_P_L_A_T_E_T_E_S_T_F_U_N_C_ ), Name, Tags, typename T,__VA_ARGS__)
#else #else
#define INTERNAL_CATCH_TEMPLATE_PRODUCT_TEST_CASE(Name, Tags, ...)\ #define INTERNAL_CATCH_TEMPLATE_PRODUCT_TEST_CASE(Name, Tags, ...)\
INTERNAL_CATCH_EXPAND_VARGS( INTERNAL_CATCH_TEMPLATE_PRODUCT_TEST_CASE2( INTERNAL_CATCH_UNIQUE_NAME( ____C_A_T_C_H____T_E_M_P_L_A_T_E____T_E_S_T____ ), INTERNAL_CATCH_UNIQUE_NAME( ____C_A_T_C_H____T_E_M_P_L_A_T_E____T_E_S_T____F_U_N_C____ ), Name, Tags, typename T, __VA_ARGS__ ) ) INTERNAL_CATCH_EXPAND_VARGS( INTERNAL_CATCH_TEMPLATE_PRODUCT_TEST_CASE2( INTERNAL_CATCH_UNIQUE_NAME( C_A_T_C_H_T_E_M_P_L_A_T_E_T_E_S_T_ ), INTERNAL_CATCH_UNIQUE_NAME( C_A_T_C_H_T_E_M_P_L_A_T_E_T_E_S_T_F_U_N_C_ ), Name, Tags, typename T, __VA_ARGS__ ) )
#endif #endif
#ifndef CATCH_CONFIG_TRADITIONAL_MSVC_PREPROCESSOR #ifndef CATCH_CONFIG_TRADITIONAL_MSVC_PREPROCESSOR
#define INTERNAL_CATCH_TEMPLATE_PRODUCT_TEST_CASE_SIG(Name, Tags, Signature, ...)\ #define INTERNAL_CATCH_TEMPLATE_PRODUCT_TEST_CASE_SIG(Name, Tags, Signature, ...)\
INTERNAL_CATCH_TEMPLATE_PRODUCT_TEST_CASE2(INTERNAL_CATCH_UNIQUE_NAME( ____C_A_T_C_H____T_E_M_P_L_A_T_E____T_E_S_T____ ), INTERNAL_CATCH_UNIQUE_NAME( ____C_A_T_C_H____T_E_M_P_L_A_T_E____T_E_S_T____F_U_N_C____ ), Name, Tags, Signature, __VA_ARGS__) INTERNAL_CATCH_TEMPLATE_PRODUCT_TEST_CASE2(INTERNAL_CATCH_UNIQUE_NAME( C_A_T_C_H_T_E_M_P_L_A_T_E_T_E_S_T_ ), INTERNAL_CATCH_UNIQUE_NAME( C_A_T_C_H_T_E_M_P_L_A_T_E_T_E_S_T_F_U_N_C_ ), Name, Tags, Signature, __VA_ARGS__)
#else #else
#define INTERNAL_CATCH_TEMPLATE_PRODUCT_TEST_CASE_SIG(Name, Tags, Signature, ...)\ #define INTERNAL_CATCH_TEMPLATE_PRODUCT_TEST_CASE_SIG(Name, Tags, Signature, ...)\
INTERNAL_CATCH_EXPAND_VARGS( INTERNAL_CATCH_TEMPLATE_PRODUCT_TEST_CASE2( INTERNAL_CATCH_UNIQUE_NAME( ____C_A_T_C_H____T_E_M_P_L_A_T_E____T_E_S_T____ ), INTERNAL_CATCH_UNIQUE_NAME( ____C_A_T_C_H____T_E_M_P_L_A_T_E____T_E_S_T____F_U_N_C____ ), Name, Tags, Signature, __VA_ARGS__ ) ) INTERNAL_CATCH_EXPAND_VARGS( INTERNAL_CATCH_TEMPLATE_PRODUCT_TEST_CASE2( INTERNAL_CATCH_UNIQUE_NAME( C_A_T_C_H_T_E_M_P_L_A_T_E_T_E_S_T_ ), INTERNAL_CATCH_UNIQUE_NAME( C_A_T_C_H_T_E_M_P_L_A_T_E_T_E_S_T_F_U_N_C_ ), Name, Tags, Signature, __VA_ARGS__ ) )
#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)\
@@ -250,7 +250,7 @@ struct AutoReg : NonCopyable {
void reg_tests() { \ void reg_tests() { \
int index = 0; \ int index = 0; \
using expander = int[]; \ using expander = int[]; \
(void)expander{(Catch::AutoReg( Catch::makeTestInvoker( &TestFunc<Types> ), CATCH_INTERNAL_LINEINFO, Catch::StringRef(), Catch::NameAndTags{ Name " - " + std::string(INTERNAL_CATCH_STRINGIZE(TmplList)) + " - " + std::to_string(index), Tags } ), index++, 0)... };/* NOLINT */\ (void)expander{(Catch::AutoReg( Catch::makeTestInvoker( &TestFunc<Types> ), CATCH_INTERNAL_LINEINFO, Catch::StringRef(), Catch::NameAndTags{ Name " - " + std::string(INTERNAL_CATCH_STRINGIZE(TmplList)) + " - " + std::to_string(index), Tags } ), index++)... };/* NOLINT */\
} \ } \
};\ };\
static int INTERNAL_CATCH_UNIQUE_NAME( globalRegistrar ) = [](){ \ static int INTERNAL_CATCH_UNIQUE_NAME( globalRegistrar ) = [](){ \
@@ -265,7 +265,7 @@ struct AutoReg : NonCopyable {
static void TestFunc() static void TestFunc()
#define INTERNAL_CATCH_TEMPLATE_LIST_TEST_CASE(Name, Tags, TmplList) \ #define INTERNAL_CATCH_TEMPLATE_LIST_TEST_CASE(Name, Tags, TmplList) \
INTERNAL_CATCH_TEMPLATE_LIST_TEST_CASE_2( INTERNAL_CATCH_UNIQUE_NAME( ____C_A_T_C_H____T_E_M_P_L_A_T_E____T_E_S_T____ ), INTERNAL_CATCH_UNIQUE_NAME( ____C_A_T_C_H____T_E_M_P_L_A_T_E____T_E_S_T____F_U_N_C____ ), Name, Tags, TmplList ) INTERNAL_CATCH_TEMPLATE_LIST_TEST_CASE_2( INTERNAL_CATCH_UNIQUE_NAME( C_A_T_C_H_T_E_M_P_L_A_T_E_T_E_S_T_ ), INTERNAL_CATCH_UNIQUE_NAME( C_A_T_C_H_T_E_M_P_L_A_T_E_T_E_S_T_F_U_N_C_ ), Name, Tags, TmplList )
#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, ... ) \
@@ -285,7 +285,7 @@ struct AutoReg : NonCopyable {
int index = 0; \ int index = 0; \
constexpr char const* tmpl_types[] = {CATCH_REC_LIST(INTERNAL_CATCH_STRINGIZE_WITHOUT_PARENS, __VA_ARGS__)};\ constexpr char const* tmpl_types[] = {CATCH_REC_LIST(INTERNAL_CATCH_STRINGIZE_WITHOUT_PARENS, __VA_ARGS__)};\
using expander = int[];\ using expander = int[];\
(void)expander{(reg_test(Types{}, #ClassName, Catch::NameAndTags{ Name " - " + std::string(tmpl_types[index]), Tags } ), index++, 0)... };/* NOLINT */ \ (void)expander{(reg_test(Types{}, #ClassName, Catch::NameAndTags{ Name " - " + std::string(tmpl_types[index]), Tags } ), index++)... };/* NOLINT */ \
}\ }\
};\ };\
static int INTERNAL_CATCH_UNIQUE_NAME( globalRegistrar ) = [](){\ static int INTERNAL_CATCH_UNIQUE_NAME( globalRegistrar ) = [](){\
@@ -299,18 +299,18 @@ struct AutoReg : NonCopyable {
#ifndef CATCH_CONFIG_TRADITIONAL_MSVC_PREPROCESSOR #ifndef CATCH_CONFIG_TRADITIONAL_MSVC_PREPROCESSOR
#define INTERNAL_CATCH_TEMPLATE_TEST_CASE_METHOD( ClassName, Name, Tags,... ) \ #define INTERNAL_CATCH_TEMPLATE_TEST_CASE_METHOD( ClassName, Name, Tags,... ) \
INTERNAL_CATCH_TEMPLATE_TEST_CASE_METHOD_2( INTERNAL_CATCH_UNIQUE_NAME( ____C_A_T_C_H____T_E_M_P_L_A_T_E____T_E_S_T____C_L_A_S_S____ ), INTERNAL_CATCH_UNIQUE_NAME( ____C_A_T_C_H____T_E_M_P_L_A_T_E____T_E_S_T____ ) , ClassName, Name, Tags, typename T, __VA_ARGS__ ) INTERNAL_CATCH_TEMPLATE_TEST_CASE_METHOD_2( INTERNAL_CATCH_UNIQUE_NAME( C_A_T_C_H_T_E_M_P_L_A_T_E_T_E_S_T_C_L_A_S_S_ ), INTERNAL_CATCH_UNIQUE_NAME( C_A_T_C_H_T_E_M_P_L_A_T_E_T_E_S_T_ ) , ClassName, Name, Tags, typename T, __VA_ARGS__ )
#else #else
#define INTERNAL_CATCH_TEMPLATE_TEST_CASE_METHOD( ClassName, Name, Tags,... ) \ #define INTERNAL_CATCH_TEMPLATE_TEST_CASE_METHOD( ClassName, Name, Tags,... ) \
INTERNAL_CATCH_EXPAND_VARGS( INTERNAL_CATCH_TEMPLATE_TEST_CASE_METHOD_2( INTERNAL_CATCH_UNIQUE_NAME( ____C_A_T_C_H____T_E_M_P_L_A_T_E____T_E_S_T____C_L_A_S_S____ ), INTERNAL_CATCH_UNIQUE_NAME( ____C_A_T_C_H____T_E_M_P_L_A_T_E____T_E_S_T____ ) , ClassName, Name, Tags, typename T, __VA_ARGS__ ) ) INTERNAL_CATCH_EXPAND_VARGS( INTERNAL_CATCH_TEMPLATE_TEST_CASE_METHOD_2( INTERNAL_CATCH_UNIQUE_NAME( C_A_T_C_H_T_E_M_P_L_A_T_E_T_E_S_T_C_L_A_S_S_ ), INTERNAL_CATCH_UNIQUE_NAME( C_A_T_C_H_T_E_M_P_L_A_T_E_T_E_S_T_ ) , ClassName, Name, Tags, typename T, __VA_ARGS__ ) )
#endif #endif
#ifndef CATCH_CONFIG_TRADITIONAL_MSVC_PREPROCESSOR #ifndef CATCH_CONFIG_TRADITIONAL_MSVC_PREPROCESSOR
#define INTERNAL_CATCH_TEMPLATE_TEST_CASE_METHOD_SIG( ClassName, Name, Tags, Signature, ... ) \ #define INTERNAL_CATCH_TEMPLATE_TEST_CASE_METHOD_SIG( ClassName, Name, Tags, Signature, ... ) \
INTERNAL_CATCH_TEMPLATE_TEST_CASE_METHOD_2( INTERNAL_CATCH_UNIQUE_NAME( ____C_A_T_C_H____T_E_M_P_L_A_T_E____T_E_S_T____C_L_A_S_S____ ), INTERNAL_CATCH_UNIQUE_NAME( ____C_A_T_C_H____T_E_M_P_L_A_T_E____T_E_S_T____ ) , ClassName, Name, Tags, Signature, __VA_ARGS__ ) INTERNAL_CATCH_TEMPLATE_TEST_CASE_METHOD_2( INTERNAL_CATCH_UNIQUE_NAME( C_A_T_C_H_T_E_M_P_L_A_T_E_T_E_S_T_C_L_A_S_S_ ), INTERNAL_CATCH_UNIQUE_NAME( C_A_T_C_H_T_E_M_P_L_A_T_E_T_E_S_T_ ) , ClassName, Name, Tags, Signature, __VA_ARGS__ )
#else #else
#define INTERNAL_CATCH_TEMPLATE_TEST_CASE_METHOD_SIG( ClassName, Name, Tags, Signature, ... ) \ #define INTERNAL_CATCH_TEMPLATE_TEST_CASE_METHOD_SIG( ClassName, Name, Tags, Signature, ... ) \
INTERNAL_CATCH_EXPAND_VARGS( INTERNAL_CATCH_TEMPLATE_TEST_CASE_METHOD_2( INTERNAL_CATCH_UNIQUE_NAME( ____C_A_T_C_H____T_E_M_P_L_A_T_E____T_E_S_T____C_L_A_S_S____ ), INTERNAL_CATCH_UNIQUE_NAME( ____C_A_T_C_H____T_E_M_P_L_A_T_E____T_E_S_T____ ) , ClassName, Name, Tags, Signature, __VA_ARGS__ ) ) INTERNAL_CATCH_EXPAND_VARGS( INTERNAL_CATCH_TEMPLATE_TEST_CASE_METHOD_2( INTERNAL_CATCH_UNIQUE_NAME( C_A_T_C_H_T_E_M_P_L_A_T_E_T_E_S_T_C_L_A_S_S_ ), INTERNAL_CATCH_UNIQUE_NAME( C_A_T_C_H_T_E_M_P_L_A_T_E_T_E_S_T_ ) , ClassName, Name, Tags, Signature, __VA_ARGS__ ) )
#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)\
@@ -334,7 +334,7 @@ struct AutoReg : NonCopyable {
constexpr char const* tmpl_types[] = {CATCH_REC_LIST(INTERNAL_CATCH_STRINGIZE_WITHOUT_PARENS, INTERNAL_CATCH_REMOVE_PARENS(TmplTypes))};\ constexpr char const* tmpl_types[] = {CATCH_REC_LIST(INTERNAL_CATCH_STRINGIZE_WITHOUT_PARENS, INTERNAL_CATCH_REMOVE_PARENS(TmplTypes))};\
constexpr char const* types_list[] = {CATCH_REC_LIST(INTERNAL_CATCH_STRINGIZE_WITHOUT_PARENS, INTERNAL_CATCH_REMOVE_PARENS(TypesList))};\ constexpr char const* types_list[] = {CATCH_REC_LIST(INTERNAL_CATCH_STRINGIZE_WITHOUT_PARENS, INTERNAL_CATCH_REMOVE_PARENS(TypesList))};\
constexpr auto num_types = sizeof(types_list) / sizeof(types_list[0]);\ constexpr auto num_types = sizeof(types_list) / sizeof(types_list[0]);\
(void)expander{(Catch::AutoReg( Catch::makeTestInvoker( &TestName<Types>::test ), CATCH_INTERNAL_LINEINFO, #ClassName, Catch::NameAndTags{ Name " - " + std::string(tmpl_types[index / num_types]) + "<" + std::string(types_list[index % num_types]) + ">", Tags } ), index++, 0)... };/* NOLINT */ \ (void)expander{(Catch::AutoReg( Catch::makeTestInvoker( &TestName<Types>::test ), CATCH_INTERNAL_LINEINFO, #ClassName, Catch::NameAndTags{ Name " - " + std::string(tmpl_types[index / num_types]) + "<" + std::string(types_list[index % num_types]) + ">", Tags } ), index++)... };/* NOLINT */ \
}\ }\
};\ };\
static int INTERNAL_CATCH_UNIQUE_NAME( globalRegistrar ) = [](){\ static int INTERNAL_CATCH_UNIQUE_NAME( globalRegistrar ) = [](){\
@@ -351,18 +351,18 @@ struct AutoReg : NonCopyable {
#ifndef CATCH_CONFIG_TRADITIONAL_MSVC_PREPROCESSOR #ifndef CATCH_CONFIG_TRADITIONAL_MSVC_PREPROCESSOR
#define INTERNAL_CATCH_TEMPLATE_PRODUCT_TEST_CASE_METHOD( ClassName, Name, Tags, ... )\ #define INTERNAL_CATCH_TEMPLATE_PRODUCT_TEST_CASE_METHOD( ClassName, Name, Tags, ... )\
INTERNAL_CATCH_TEMPLATE_PRODUCT_TEST_CASE_METHOD_2( INTERNAL_CATCH_UNIQUE_NAME( ____C_A_T_C_H____T_E_M_P_L_A_T_E____T_E_S_T____ ), INTERNAL_CATCH_UNIQUE_NAME( ____C_A_T_C_H____T_E_M_P_L_A_T_E____T_E_S_T____F_U_N_C____ ), ClassName, Name, Tags, typename T, __VA_ARGS__ ) INTERNAL_CATCH_TEMPLATE_PRODUCT_TEST_CASE_METHOD_2( INTERNAL_CATCH_UNIQUE_NAME( C_A_T_C_H_T_E_M_P_L_A_T_E_T_E_S_T_ ), INTERNAL_CATCH_UNIQUE_NAME( C_A_T_C_H_T_E_M_P_L_A_T_E_T_E_S_T_F_U_N_C_ ), ClassName, Name, Tags, typename T, __VA_ARGS__ )
#else #else
#define INTERNAL_CATCH_TEMPLATE_PRODUCT_TEST_CASE_METHOD( ClassName, Name, Tags, ... )\ #define INTERNAL_CATCH_TEMPLATE_PRODUCT_TEST_CASE_METHOD( ClassName, Name, Tags, ... )\
INTERNAL_CATCH_EXPAND_VARGS( INTERNAL_CATCH_TEMPLATE_PRODUCT_TEST_CASE_METHOD_2( INTERNAL_CATCH_UNIQUE_NAME( ____C_A_T_C_H____T_E_M_P_L_A_T_E____T_E_S_T____ ), INTERNAL_CATCH_UNIQUE_NAME( ____C_A_T_C_H____T_E_M_P_L_A_T_E____T_E_S_T____F_U_N_C____ ), ClassName, Name, Tags, typename T,__VA_ARGS__ ) ) INTERNAL_CATCH_EXPAND_VARGS( INTERNAL_CATCH_TEMPLATE_PRODUCT_TEST_CASE_METHOD_2( INTERNAL_CATCH_UNIQUE_NAME( C_A_T_C_H_T_E_M_P_L_A_T_E_T_E_S_T_ ), INTERNAL_CATCH_UNIQUE_NAME( C_A_T_C_H_T_E_M_P_L_A_T_E_T_E_S_T_F_U_N_C_ ), ClassName, Name, Tags, typename T,__VA_ARGS__ ) )
#endif #endif
#ifndef CATCH_CONFIG_TRADITIONAL_MSVC_PREPROCESSOR #ifndef CATCH_CONFIG_TRADITIONAL_MSVC_PREPROCESSOR
#define INTERNAL_CATCH_TEMPLATE_PRODUCT_TEST_CASE_METHOD_SIG( ClassName, Name, Tags, Signature, ... )\ #define INTERNAL_CATCH_TEMPLATE_PRODUCT_TEST_CASE_METHOD_SIG( ClassName, Name, Tags, Signature, ... )\
INTERNAL_CATCH_TEMPLATE_PRODUCT_TEST_CASE_METHOD_2( INTERNAL_CATCH_UNIQUE_NAME( ____C_A_T_C_H____T_E_M_P_L_A_T_E____T_E_S_T____ ), INTERNAL_CATCH_UNIQUE_NAME( ____C_A_T_C_H____T_E_M_P_L_A_T_E____T_E_S_T____F_U_N_C____ ), ClassName, Name, Tags, Signature, __VA_ARGS__ ) INTERNAL_CATCH_TEMPLATE_PRODUCT_TEST_CASE_METHOD_2( INTERNAL_CATCH_UNIQUE_NAME( C_A_T_C_H_T_E_M_P_L_A_T_E_T_E_S_T_ ), INTERNAL_CATCH_UNIQUE_NAME( C_A_T_C_H_T_E_M_P_L_A_T_E_T_E_S_T_F_U_N_C_ ), ClassName, Name, Tags, Signature, __VA_ARGS__ )
#else #else
#define INTERNAL_CATCH_TEMPLATE_PRODUCT_TEST_CASE_METHOD_SIG( ClassName, Name, Tags, Signature, ... )\ #define INTERNAL_CATCH_TEMPLATE_PRODUCT_TEST_CASE_METHOD_SIG( ClassName, Name, Tags, Signature, ... )\
INTERNAL_CATCH_EXPAND_VARGS( INTERNAL_CATCH_TEMPLATE_PRODUCT_TEST_CASE_METHOD_2( INTERNAL_CATCH_UNIQUE_NAME( ____C_A_T_C_H____T_E_M_P_L_A_T_E____T_E_S_T____ ), INTERNAL_CATCH_UNIQUE_NAME( ____C_A_T_C_H____T_E_M_P_L_A_T_E____T_E_S_T____F_U_N_C____ ), ClassName, Name, Tags, Signature,__VA_ARGS__ ) ) INTERNAL_CATCH_EXPAND_VARGS( INTERNAL_CATCH_TEMPLATE_PRODUCT_TEST_CASE_METHOD_2( INTERNAL_CATCH_UNIQUE_NAME( C_A_T_C_H_T_E_M_P_L_A_T_E_T_E_S_T_ ), INTERNAL_CATCH_UNIQUE_NAME( C_A_T_C_H_T_E_M_P_L_A_T_E_T_E_S_T_F_U_N_C_ ), ClassName, Name, Tags, Signature,__VA_ARGS__ ) )
#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) \
@@ -381,7 +381,7 @@ struct AutoReg : NonCopyable {
void reg_tests(){\ void reg_tests(){\
int index = 0;\ int index = 0;\
using expander = int[];\ using expander = int[];\
(void)expander{(Catch::AutoReg( Catch::makeTestInvoker( &TestName<Types>::test ), CATCH_INTERNAL_LINEINFO, #ClassName, Catch::NameAndTags{ Name " - " + std::string(INTERNAL_CATCH_STRINGIZE(TmplList)) + " - " + std::to_string(index), Tags } ), index++, 0)... };/* NOLINT */ \ (void)expander{(Catch::AutoReg( Catch::makeTestInvoker( &TestName<Types>::test ), CATCH_INTERNAL_LINEINFO, #ClassName, Catch::NameAndTags{ Name " - " + std::string(INTERNAL_CATCH_STRINGIZE(TmplList)) + " - " + std::to_string(index), Tags } ), index++)... };/* NOLINT */ \
}\ }\
};\ };\
static int INTERNAL_CATCH_UNIQUE_NAME( globalRegistrar ) = [](){\ static int INTERNAL_CATCH_UNIQUE_NAME( globalRegistrar ) = [](){\
@@ -396,7 +396,7 @@ struct AutoReg : NonCopyable {
void TestName<TestType>::test() void TestName<TestType>::test()
#define INTERNAL_CATCH_TEMPLATE_LIST_TEST_CASE_METHOD(ClassName, Name, Tags, TmplList) \ #define INTERNAL_CATCH_TEMPLATE_LIST_TEST_CASE_METHOD(ClassName, Name, Tags, TmplList) \
INTERNAL_CATCH_TEMPLATE_LIST_TEST_CASE_METHOD_2( INTERNAL_CATCH_UNIQUE_NAME( ____C_A_T_C_H____T_E_M_P_L_A_T_E____T_E_S_T____ ), INTERNAL_CATCH_UNIQUE_NAME( ____C_A_T_C_H____T_E_M_P_L_A_T_E____T_E_S_T____F_U_N_C____ ), ClassName, Name, Tags, TmplList ) INTERNAL_CATCH_TEMPLATE_LIST_TEST_CASE_METHOD_2( INTERNAL_CATCH_UNIQUE_NAME( C_A_T_C_H_T_E_M_P_L_A_T_E_T_E_S_T_ ), INTERNAL_CATCH_UNIQUE_NAME( C_A_T_C_H_T_E_M_P_L_A_T_E_T_E_S_T_F_U_N_C_ ), ClassName, Name, Tags, TmplList )
#endif // TWOBLUECUBES_CATCH_TEST_REGISTRY_HPP_INCLUDED #endif // TWOBLUECUBES_CATCH_TEST_REGISTRY_HPP_INCLUDED

View File

@@ -168,6 +168,7 @@ namespace Catch {
m_pos = m_arg.size(); m_pos = m_arg.size();
m_substring.clear(); m_substring.clear();
m_patternName.clear(); m_patternName.clear();
m_realPatternPos = 0;
return false; return false;
} }
endMode(); endMode();
@@ -186,6 +187,7 @@ namespace Catch {
} }
m_patternName.clear(); m_patternName.clear();
m_realPatternPos = 0;
return token; return token;
} }

View File

@@ -309,8 +309,8 @@ namespace Catch {
#endif #endif
namespace Detail { namespace Detail {
template<typename InputIterator> template<typename InputIterator, typename Sentinel = InputIterator>
std::string rangeToString(InputIterator first, InputIterator last) { std::string rangeToString(InputIterator first, Sentinel last) {
ReusableStringStream rss; ReusableStringStream rss;
rss << "{ "; rss << "{ ";
if (first != last) { if (first != last) {
@@ -469,20 +469,27 @@ namespace Catch {
#endif // CATCH_CONFIG_ENABLE_VARIANT_STRINGMAKER #endif // CATCH_CONFIG_ENABLE_VARIANT_STRINGMAKER
namespace Catch { namespace Catch {
struct not_this_one {}; // Tag type for detecting which begin/ end are being selected // Import begin/ end from std here
// Import begin/ end from std here so they are considered alongside the fallback (...) overloads in this namespace
using std::begin; using std::begin;
using std::end; using std::end;
not_this_one begin( ... ); namespace detail {
not_this_one end( ... ); template <typename...>
struct void_type {
using type = void;
};
template <typename T, typename = void>
struct is_range_impl : std::false_type {
};
template <typename T>
struct is_range_impl<T, typename void_type<decltype(begin(std::declval<T>()))>::type> : std::true_type {
};
} // namespace detail
template <typename T> template <typename T>
struct is_range { struct is_range : detail::is_range_impl<T> {
static const bool value =
!std::is_same<decltype(begin(std::declval<T>())), not_this_one>::value &&
!std::is_same<decltype(end(std::declval<T>())), not_this_one>::value;
}; };
#if defined(_MANAGED) // Managed types are never ranges #if defined(_MANAGED) // Managed types are never ranges

View File

@@ -8,11 +8,15 @@
#include "catch_compiler_capabilities.h" #include "catch_compiler_capabilities.h"
#include "catch_uncaught_exceptions.h" #include "catch_uncaught_exceptions.h"
#include "catch_config_uncaught_exceptions.hpp"
#include <exception> #include <exception>
namespace Catch { namespace Catch {
bool uncaught_exceptions() { bool uncaught_exceptions() {
#if defined(CATCH_CONFIG_CPP17_UNCAUGHT_EXCEPTIONS) #if defined(CATCH_CONFIG_DISABLE_EXCEPTIONS)
return false;
#elif defined(CATCH_CONFIG_CPP17_UNCAUGHT_EXCEPTIONS)
return std::uncaught_exceptions() > 0; return std::uncaught_exceptions() > 0;
#else #else
return std::uncaught_exception(); return std::uncaught_exception();

View File

@@ -37,7 +37,7 @@ namespace Catch {
} }
Version const& libraryVersion() { Version const& libraryVersion() {
static Version version( 2, 11, 3, "", 0 ); static Version version( 2, 13, 8, "", 0 );
return version; return version;
} }

View File

@@ -41,6 +41,17 @@ namespace Catch {
return std::string(buffer); return std::string(buffer);
} }
bool shouldShowDuration( IConfig const& config, double duration ) {
if ( config.showDurations() == ShowDurations::Always ) {
return true;
}
if ( config.showDurations() == ShowDurations::Never ) {
return false;
}
const double min = config.minDuration();
return min >= 0 && duration >= min;
}
std::string serializeFilters( std::vector<std::string> const& container ) { std::string serializeFilters( std::vector<std::string> const& container ) {
ReusableStringStream oss; ReusableStringStream oss;
bool first = true; bool first = true;

View File

@@ -25,6 +25,9 @@ namespace Catch {
// Returns double formatted as %.3f (format expected on output) // Returns double formatted as %.3f (format expected on output)
std::string getFormattedDuration( double duration ); std::string getFormattedDuration( double duration );
//! Should the reporter show
bool shouldShowDuration( IConfig const& config, double duration );
std::string serializeFilters( std::vector<std::string> const& container ); std::string serializeFilters( std::vector<std::string> const& container );
template<typename DerivedT> template<typename DerivedT>
@@ -52,7 +55,7 @@ namespace Catch {
void noMatchingTestCases(std::string const&) override {} void noMatchingTestCases(std::string const&) override {}
void reportInvalidArguments(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;
} }

View File

@@ -245,10 +245,6 @@ private:
return "Reports test results on a single line, suitable for IDEs"; return "Reports test results on a single line, suitable for IDEs";
} }
ReporterPreferences CompactReporter::getPreferences() const {
return m_reporterPrefs;
}
void CompactReporter::noMatchingTestCases( std::string const& spec ) { void CompactReporter::noMatchingTestCases( std::string const& spec ) {
stream << "No test cases matched '" << spec << '\'' << std::endl; stream << "No test cases matched '" << spec << '\'' << std::endl;
} }
@@ -275,8 +271,9 @@ private:
} }
void CompactReporter::sectionEnded(SectionStats const& _sectionStats) { void CompactReporter::sectionEnded(SectionStats const& _sectionStats) {
if (m_config->showDurations() == ShowDurations::Always) { double dur = _sectionStats.durationInSeconds;
stream << getFormattedDuration(_sectionStats.durationInSeconds) << " s: " << _sectionStats.sectionInfo.name << std::endl; if ( shouldShowDuration( *m_config, dur ) ) {
stream << getFormattedDuration( dur ) << " s: " << _sectionStats.sectionInfo.name << std::endl;
} }
} }

View File

@@ -22,8 +22,6 @@ namespace Catch {
static std::string getDescription(); static std::string getDescription();
ReporterPreferences getPreferences() const override;
void noMatchingTestCases(std::string const& spec) override; void noMatchingTestCases(std::string const& spec) override;
void assertionStarting(AssertionInfo const&) override; void assertionStarting(AssertionInfo const&) override;

View File

@@ -362,7 +362,7 @@ ConsoleReporter::ConsoleReporter(ReporterConfig const& config)
else else
{ {
return{ return{
{ "benchmark name", CATCH_CONFIG_CONSOLE_WIDTH - 32, ColumnInfo::Left }, { "benchmark name", CATCH_CONFIG_CONSOLE_WIDTH - 43, ColumnInfo::Left },
{ "samples mean std dev", 14, ColumnInfo::Right }, { "samples mean std dev", 14, ColumnInfo::Right },
{ "iterations low mean low std dev", 14, ColumnInfo::Right }, { "iterations low mean low std dev", 14, ColumnInfo::Right },
{ "estimated high mean high std dev", 14, ColumnInfo::Right } { "estimated high mean high std dev", 14, ColumnInfo::Right }
@@ -418,8 +418,9 @@ void ConsoleReporter::sectionEnded(SectionStats const& _sectionStats) {
stream << "\nNo assertions in test case"; stream << "\nNo assertions in test case";
stream << " '" << _sectionStats.sectionInfo.name << "'\n" << std::endl; stream << " '" << _sectionStats.sectionInfo.name << "'\n" << std::endl;
} }
if (m_config->showDurations() == ShowDurations::Always) { double dur = _sectionStats.durationInSeconds;
stream << getFormattedDuration(_sectionStats.durationInSeconds) << " s: " << _sectionStats.sectionInfo.name << std::endl; if (shouldShowDuration(*m_config, dur)) {
stream << getFormattedDuration(dur) << " s: " << _sectionStats.sectionInfo.name << std::endl;
} }
if (m_headerPrinted) { if (m_headerPrinted) {
m_headerPrinted = false; m_headerPrinted = false;

View File

@@ -18,6 +18,7 @@
#include <sstream> #include <sstream>
#include <ctime> #include <ctime>
#include <algorithm> #include <algorithm>
#include <iomanip>
namespace Catch { namespace Catch {
@@ -45,7 +46,7 @@ namespace Catch {
#else #else
std::strftime(timeStamp, timeStampSize, fmt, timeInfo); std::strftime(timeStamp, timeStampSize, fmt, timeInfo);
#endif #endif
return std::string(timeStamp); return std::string(timeStamp, timeStampSize-1);
} }
std::string fileNameTag(const std::vector<std::string> &tags) { std::string fileNameTag(const std::vector<std::string> &tags) {
@@ -56,6 +57,17 @@ namespace Catch {
return it->substr(1); return it->substr(1);
return std::string(); return std::string();
} }
// Formats the duration in seconds to 3 decimal places.
// This is done because some genius defined Maven Surefire schema
// in a way that only accepts 3 decimal places, and tools like
// Jenkins use that schema for validation JUnit reporter output.
std::string formatDuration( double seconds ) {
ReusableStringStream rss;
rss << std::fixed << std::setprecision( 3 ) << seconds;
return rss.str();
}
} // anonymous namespace } // anonymous namespace
JunitReporter::JunitReporter( ReporterConfig const& _config ) JunitReporter::JunitReporter( ReporterConfig const& _config )
@@ -125,7 +137,7 @@ namespace Catch {
if( m_config->showDurations() == ShowDurations::Never ) if( m_config->showDurations() == ShowDurations::Never )
xml.writeAttribute( "time", "" ); xml.writeAttribute( "time", "" );
else else
xml.writeAttribute( "time", suiteTime ); xml.writeAttribute( "time", formatDuration( suiteTime ) );
xml.writeAttribute( "timestamp", getCurrentTimestamp() ); xml.writeAttribute( "timestamp", getCurrentTimestamp() );
// Write properties if there are any // Write properties if there are any
@@ -170,12 +182,13 @@ namespace Catch {
if ( !m_config->name().empty() ) if ( !m_config->name().empty() )
className = m_config->name() + "." + className; className = m_config->name() + "." + className;
writeSection( className, "", rootSection ); writeSection( className, "", rootSection, stats.testInfo.okToFail() );
} }
void JunitReporter::writeSection( std::string const& className, void JunitReporter::writeSection( std::string const& className,
std::string const& rootName, std::string const& rootName,
SectionNode const& sectionNode ) { SectionNode const& sectionNode,
bool testOkToFail) {
std::string name = trim( sectionNode.stats.sectionInfo.name ); std::string name = trim( sectionNode.stats.sectionInfo.name );
if( !rootName.empty() ) if( !rootName.empty() )
name = rootName + '/' + name; name = rootName + '/' + name;
@@ -192,10 +205,21 @@ namespace Catch {
xml.writeAttribute( "classname", className ); xml.writeAttribute( "classname", className );
xml.writeAttribute( "name", name ); xml.writeAttribute( "name", name );
} }
xml.writeAttribute( "time", ::Catch::Detail::stringify( sectionNode.stats.durationInSeconds ) ); xml.writeAttribute( "time", formatDuration( sectionNode.stats.durationInSeconds ) );
// This is not ideal, but it should be enough to mimic gtest's
// junit output.
// Ideally the JUnit reporter would also handle `skipTest`
// events and write those out appropriately.
xml.writeAttribute( "status", "run" );
if (sectionNode.stats.assertions.failedButOk) {
xml.scopedElement("skipped")
.writeAttribute("message", "TEST_CASE tagged with !mayfail");
}
writeAssertions( sectionNode ); writeAssertions( sectionNode );
if( !sectionNode.stdOut.empty() ) if( !sectionNode.stdOut.empty() )
xml.scopedElement( "system-out" ).writeText( trim( sectionNode.stdOut ), XmlFormatting::Newline ); xml.scopedElement( "system-out" ).writeText( trim( sectionNode.stdOut ), XmlFormatting::Newline );
if( !sectionNode.stdErr.empty() ) if( !sectionNode.stdErr.empty() )
@@ -203,9 +227,9 @@ namespace Catch {
} }
for( auto const& childNode : sectionNode.childSections ) for( auto const& childNode : sectionNode.childSections )
if( className.empty() ) if( className.empty() )
writeSection( name, "", *childNode ); writeSection( name, "", *childNode, testOkToFail );
else else
writeSection( className, name, *childNode ); writeSection( className, name, *childNode, testOkToFail );
} }
void JunitReporter::writeAssertions( SectionNode const& sectionNode ) { void JunitReporter::writeAssertions( SectionNode const& sectionNode ) {

View File

@@ -41,9 +41,10 @@ namespace Catch {
void writeTestCase(TestCaseNode const& testCaseNode); void writeTestCase(TestCaseNode const& testCaseNode);
void writeSection(std::string const& className, void writeSection( std::string const& className,
std::string const& rootName, std::string const& rootName,
SectionNode const& sectionNode); SectionNode const& sectionNode,
bool testOkToFail );
void writeAssertions(SectionNode const& sectionNode); void writeAssertions(SectionNode const& sectionNode);
void writeAssertion(AssertionStats const& stats); void writeAssertion(AssertionStats const& stats);

View File

@@ -23,16 +23,17 @@ namespace Catch {
using StreamingReporterBase::StreamingReporterBase; using StreamingReporterBase::StreamingReporterBase;
TAPReporter( ReporterConfig const& config ):
StreamingReporterBase( config ) {
m_reporterPrefs.shouldReportAllAssertions = true;
}
~TAPReporter() override; ~TAPReporter() override;
static std::string getDescription() { static std::string getDescription() {
return "Reports test results in TAP format, suitable for test harnesses"; return "Reports test results in TAP format, suitable for test harnesses";
} }
ReporterPreferences getPreferences() const override {
return m_reporterPrefs;
}
void noMatchingTestCases( std::string const& spec ) override { void noMatchingTestCases( std::string const& spec ) override {
stream << "# No test cases matched '" << spec << "'" << std::endl; stream << "# No test cases matched '" << spec << "'" << std::endl;
} }
@@ -203,16 +204,15 @@ namespace Catch {
return; return;
} }
// using messages.end() directly (or auto) yields compilation error: const auto itEnd = messages.cend();
std::vector<MessageInfo>::const_iterator itEnd = messages.end(); const auto N = static_cast<std::size_t>( std::distance( itMessage, itEnd ) );
const std::size_t N = static_cast<std::size_t>( std::distance( itMessage, itEnd ) );
{ {
Colour colourGuard( colour ); Colour colourGuard( colour );
stream << " with " << pluralise( N, "message" ) << ":"; stream << " with " << pluralise( N, "message" ) << ":";
} }
for(; itMessage != itEnd; ) { while( itMessage != itEnd ) {
// If this assertion is a warning ignore any INFO messages // If this assertion is a warning ignore any INFO messages
if( printInfoMessages || itMessage->type != ResultWas::Info ) { if( printInfoMessages || itMessage->type != ResultWas::Info ) {
stream << " '" << itMessage->message << "'"; stream << " '" << itMessage->message << "'";
@@ -220,7 +220,9 @@ namespace Catch {
Colour colourGuard( dimColour() ); Colour colourGuard( dimColour() );
stream << " and"; stream << " and";
} }
continue;
} }
++itMessage;
} }
} }
@@ -234,10 +236,9 @@ namespace Catch {
}; };
void printTotals( const Totals& totals ) const { void printTotals( const Totals& totals ) const {
stream << "1.." << totals.assertions.total();
if( totals.testCases.total() == 0 ) { if( totals.testCases.total() == 0 ) {
stream << "1..0 # Skipped: No tests ran."; stream << " # Skipped: No tests ran.";
} else {
stream << "1.." << counter;
} }
} }
}; };

View File

@@ -207,6 +207,10 @@ namespace Catch {
.writeAttribute( "successes", testGroupStats.totals.assertions.passed ) .writeAttribute( "successes", testGroupStats.totals.assertions.passed )
.writeAttribute( "failures", testGroupStats.totals.assertions.failed ) .writeAttribute( "failures", testGroupStats.totals.assertions.failed )
.writeAttribute( "expectedFailures", testGroupStats.totals.assertions.failedButOk ); .writeAttribute( "expectedFailures", testGroupStats.totals.assertions.failedButOk );
m_xml.scopedElement( "OverallResultsCases")
.writeAttribute( "successes", testGroupStats.totals.testCases.passed )
.writeAttribute( "failures", testGroupStats.totals.testCases.failed )
.writeAttribute( "expectedFailures", testGroupStats.totals.testCases.failedButOk );
m_xml.endElement(); m_xml.endElement();
} }
@@ -216,6 +220,10 @@ namespace Catch {
.writeAttribute( "successes", testRunStats.totals.assertions.passed ) .writeAttribute( "successes", testRunStats.totals.assertions.passed )
.writeAttribute( "failures", testRunStats.totals.assertions.failed ) .writeAttribute( "failures", testRunStats.totals.assertions.failed )
.writeAttribute( "expectedFailures", testRunStats.totals.assertions.failedButOk ); .writeAttribute( "expectedFailures", testRunStats.totals.assertions.failedButOk );
m_xml.scopedElement( "OverallResultsCases")
.writeAttribute( "successes", testRunStats.totals.testCases.passed )
.writeAttribute( "failures", testRunStats.totals.testCases.failed )
.writeAttribute( "expectedFailures", testRunStats.totals.testCases.failedButOk );
m_xml.endElement(); m_xml.endElement();
} }

View File

@@ -27,6 +27,7 @@ set(TEST_SOURCES
${SELF_TEST_DIR}/IntrospectiveTests/StringManip.tests.cpp ${SELF_TEST_DIR}/IntrospectiveTests/StringManip.tests.cpp
${SELF_TEST_DIR}/IntrospectiveTests/Xml.tests.cpp ${SELF_TEST_DIR}/IntrospectiveTests/Xml.tests.cpp
${SELF_TEST_DIR}/IntrospectiveTests/ToString.tests.cpp ${SELF_TEST_DIR}/IntrospectiveTests/ToString.tests.cpp
${SELF_TEST_DIR}/TimingTests/Sleep.tests.cpp
${SELF_TEST_DIR}/UsageTests/Approx.tests.cpp ${SELF_TEST_DIR}/UsageTests/Approx.tests.cpp
${SELF_TEST_DIR}/UsageTests/BDD.tests.cpp ${SELF_TEST_DIR}/UsageTests/BDD.tests.cpp
${SELF_TEST_DIR}/UsageTests/Benchmark.tests.cpp ${SELF_TEST_DIR}/UsageTests/Benchmark.tests.cpp
@@ -123,6 +124,7 @@ set(INTERNAL_HEADERS
${HEADER_DIR}/internal/catch_common.h ${HEADER_DIR}/internal/catch_common.h
${HEADER_DIR}/internal/catch_compiler_capabilities.h ${HEADER_DIR}/internal/catch_compiler_capabilities.h
${HEADER_DIR}/internal/catch_config.hpp ${HEADER_DIR}/internal/catch_config.hpp
${HEADER_DIR}/internal/catch_config_uncaught_exceptions.hpp
${HEADER_DIR}/internal/catch_console_colour.h ${HEADER_DIR}/internal/catch_console_colour.h
${HEADER_DIR}/internal/catch_context.h ${HEADER_DIR}/internal/catch_context.h
${HEADER_DIR}/internal/catch_debug_console.h ${HEADER_DIR}/internal/catch_debug_console.h
@@ -417,6 +419,33 @@ set_tests_properties(FilteredSection-1 PROPERTIES FAIL_REGULAR_EXPRESSION "No te
add_test(NAME FilteredSection-2 COMMAND $<TARGET_FILE:SelfTest> \#1394\ nested -c NestedRunSection -c s1) add_test(NAME FilteredSection-2 COMMAND $<TARGET_FILE:SelfTest> \#1394\ nested -c NestedRunSection -c s1)
set_tests_properties(FilteredSection-2 PROPERTIES FAIL_REGULAR_EXPRESSION "No tests ran") set_tests_properties(FilteredSection-2 PROPERTIES FAIL_REGULAR_EXPRESSION "No tests ran")
add_test(
NAME
FilteredSection::GeneratorsDontCauseInfiniteLoop-1
COMMAND
$<TARGET_FILE:SelfTest> "#2025: original repro" -c "fov_0"
)
set_tests_properties(FilteredSection::GeneratorsDontCauseInfiniteLoop-1
PROPERTIES
PASS_REGULAR_EXPRESSION "inside with fov: 0" # This should happen
FAIL_REGULAR_EXPRESSION "inside with fov: 1" # This would mean there was no filtering
)
# GENERATE between filtered sections (both are selected)
add_test(
NAME
FilteredSection::GeneratorsDontCauseInfiniteLoop-2
COMMAND
$<TARGET_FILE:SelfTest> "#2025: same-level sections"
-c "A"
-c "B"
)
set_tests_properties(FilteredSection::GeneratorsDontCauseInfiniteLoop-2
PROPERTIES
PASS_REGULAR_EXPRESSION "All tests passed \\(4 assertions in 1 test case\\)"
)
# AppVeyor has a Python 2.7 in path, but doesn't have .py files as autorunnable # AppVeyor has a Python 2.7 in path, but doesn't have .py files as autorunnable
add_test(NAME ApprovalTests COMMAND ${PYTHON_EXECUTABLE} ${CATCH_DIR}/scripts/approvalTests.py $<TARGET_FILE:SelfTest>) add_test(NAME ApprovalTests COMMAND ${PYTHON_EXECUTABLE} ${CATCH_DIR}/scripts/approvalTests.py $<TARGET_FILE:SelfTest>)
set_tests_properties(ApprovalTests PROPERTIES FAIL_REGULAR_EXPRESSION "Results differed") set_tests_properties(ApprovalTests PROPERTIES FAIL_REGULAR_EXPRESSION "Results differed")
@@ -451,6 +480,8 @@ set_tests_properties(TestsInFile::InvalidTestNames-1 PROPERTIES PASS_REGULAR_EXP
add_test(NAME TestsInFile::InvalidTestNames-2 COMMAND $<TARGET_FILE:SelfTest> "-f ${CATCH_DIR}/projects/SelfTest/Misc/invalid-test-names.input") 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") set_tests_properties(TestsInFile::InvalidTestNames-2 PROPERTIES PASS_REGULAR_EXPRESSION "No tests ran")
add_test(NAME RandomTestOrdering COMMAND ${PYTHON_EXECUTABLE}
${CATCH_DIR}/projects/TestScripts/testRandomOrder.py $<TARGET_FILE:SelfTest>)
if (CATCH_USE_VALGRIND) if (CATCH_USE_VALGRIND)
add_test(NAME ValgrindRunTests COMMAND valgrind --leak-check=full --error-exitcode=1 $<TARGET_FILE:SelfTest>) add_test(NAME ValgrindRunTests COMMAND valgrind --leak-check=full --error-exitcode=1 $<TARGET_FILE:SelfTest>)

View File

@@ -10,6 +10,40 @@ project( Catch2ExtraTests LANGUAGES CXX )
message( STATUS "Extra tests included" ) message( STATUS "Extra tests included" )
# The MinDuration reporting tests do not need separate compilation, but
# they have non-trivial execution time, so they are categorized as
# extra tests, so that they are run less.
add_test(NAME MinDuration::SimpleThreshold COMMAND $<TARGET_FILE:SelfTest> --min-duration 0.22 [min_duration_test])
set_tests_properties(
MinDuration::SimpleThreshold
PROPERTIES
PASS_REGULAR_EXPRESSION "s: sleep_for_250ms"
FAIL_REGULAR_EXPRESSION "sleep_for_100ms"
RUN_SERIAL ON # The test is timing sensitive, so we want to run it
# serially to avoid false positives on oversubscribed machines
)
# -d yes overrides the threshold, so we should see the faster test even
# with a ridiculous high min duration threshold
add_test(NAME MinDuration::DurationOverrideYes COMMAND $<TARGET_FILE:SelfTest> --min-duration 1.0 -d yes [min_duration_test])
set_tests_properties(
MinDuration::DurationOverrideYes
PROPERTIES
PASS_REGULAR_EXPRESSION "s: sleep_for_100ms"
)
# -d no overrides the threshold, so we should never see any tests even
# with ridiculously low min duration threshold
add_test(NAME MinDuration::DurationOverrideNo COMMAND $<TARGET_FILE:SelfTest> --min-duration 0.0001 -d no [min_duration_test])
set_tests_properties(
MinDuration::DurationOverrideNo
PROPERTIES
FAIL_REGULAR_EXPRESSION "sleep_for_250ms"
)
# ------------ end of duration reporting tests
# define folders used: # define folders used:
set( TESTS_DIR ${CATCH_DIR}/projects/ExtraTests ) set( TESTS_DIR ${CATCH_DIR}/projects/ExtraTests )
@@ -123,7 +157,7 @@ add_test(NAME BenchmarkingMacros COMMAND BenchmarkingMacros -r console -s)
set_tests_properties( set_tests_properties(
BenchmarkingMacros BenchmarkingMacros
PROPERTIES PROPERTIES
PASS_REGULAR_EXPRESSION "benchmark name samples iterations estimated" PASS_REGULAR_EXPRESSION "benchmark name[\\r\\n\\t ]+samples[\\r\\n\\t ]+iterations[\\r\\n\\t ]+estimated"
) )
# This test touches windows.h, so it should only be compiled under msvc # This test touches windows.h, so it should only be compiled under msvc

View File

@@ -23,6 +23,64 @@ This would not be caught previously
Nor would this Nor would this
Tricky.tests.cpp:<line number>: failed: explicitly with 1 message: '1514' Tricky.tests.cpp:<line number>: failed: explicitly with 1 message: '1514'
Compilation.tests.cpp:<line number>: passed: std::is_same<TypeList<int>, TypeList<int>>::value for: true Compilation.tests.cpp:<line number>: passed: std::is_same<TypeList<int>, TypeList<int>>::value for: true
CmdLine.tests.cpp:<line number>: passed: spec.matches(fakeTestCase("spec . char")) for: true
CmdLine.tests.cpp:<line number>: passed: spec.matches(fakeTestCase("spec , char")) for: true
CmdLine.tests.cpp:<line number>: passed: !(spec.matches(fakeTestCase(R"(spec \, char)"))) for: !false
CmdLine.tests.cpp:<line number>: passed: spec.matches(fakeTestCase(R"(spec {a} char)")) for: true
CmdLine.tests.cpp:<line number>: passed: spec.matches(fakeTestCase(R"(spec [a] char)")) for: true
CmdLine.tests.cpp:<line number>: passed: !(spec.matches(fakeTestCase("differs but has similar tag", "[a]"))) for: !false
CmdLine.tests.cpp:<line number>: passed: spec.matches(fakeTestCase(R"(spec \ char)")) for: true
Generators.tests.cpp:<line number>: passed: counter < 7 for: 3 < 7
Generators.tests.cpp:<line number>: passed: counter < 7 for: 6 < 7
Generators.tests.cpp:<line number>: passed: i != j for: 1 != 3
Generators.tests.cpp:<line number>: passed: i != j for: 1 != 4
Generators.tests.cpp:<line number>: passed: i != j for: 2 != 3
Generators.tests.cpp:<line number>: passed: i != j for: 2 != 4
PartTracker.tests.cpp:<line number>: passed: with 1 message: 'A'
PartTracker.tests.cpp:<line number>: passed: m for: 1
PartTracker.tests.cpp:<line number>: passed: m for: 2
PartTracker.tests.cpp:<line number>: passed: m for: 3
PartTracker.tests.cpp:<line number>: passed: 1
PartTracker.tests.cpp:<line number>: passed: m for: 2
PartTracker.tests.cpp:<line number>: passed: m for: 3
PartTracker.tests.cpp:<line number>: passed: m for: 1
PartTracker.tests.cpp:<line number>: passed: m for: 2
PartTracker.tests.cpp:<line number>: passed: m for: 3
PartTracker.tests.cpp:<line number>: passed: with 1 message: 'A'
PartTracker.tests.cpp:<line number>: passed: with 3 messages: 'i := 1' and 'j := 3' and 'k := 5'
PartTracker.tests.cpp:<line number>: passed: with 1 message: 'B'
PartTracker.tests.cpp:<line number>: passed: with 3 messages: 'i := 1' and 'j := 3' and 'k := 6'
PartTracker.tests.cpp:<line number>: passed: with 1 message: 'B'
PartTracker.tests.cpp:<line number>: passed: with 3 messages: 'i := 1' and 'j := 4' and 'k := 5'
PartTracker.tests.cpp:<line number>: passed: with 3 messages: 'i := 1' and 'j := 4' and 'k := 6'
PartTracker.tests.cpp:<line number>: passed: with 1 message: 'A'
PartTracker.tests.cpp:<line number>: passed: with 3 messages: 'i := 2' and 'j := 3' and 'k := 5'
PartTracker.tests.cpp:<line number>: passed: with 1 message: 'B'
PartTracker.tests.cpp:<line number>: passed: with 3 messages: 'i := 2' and 'j := 3' and 'k := 6'
PartTracker.tests.cpp:<line number>: passed: with 1 message: 'B'
PartTracker.tests.cpp:<line number>: passed: with 3 messages: 'i := 2' and 'j := 4' and 'k := 5'
PartTracker.tests.cpp:<line number>: passed: with 3 messages: 'i := 2' and 'j := 4' and 'k := 6'
PartTracker.tests.cpp:<line number>: passed: m for: 1
PartTracker.tests.cpp:<line number>: passed: n for: 1
PartTracker.tests.cpp:<line number>: passed: m for: 1
PartTracker.tests.cpp:<line number>: passed: n for: 2
PartTracker.tests.cpp:<line number>: passed: m for: 1
PartTracker.tests.cpp:<line number>: passed: n for: 3
PartTracker.tests.cpp:<line number>: passed: m for: 2
PartTracker.tests.cpp:<line number>: passed: n for: 1
PartTracker.tests.cpp:<line number>: passed: m for: 2
PartTracker.tests.cpp:<line number>: passed: n for: 2
PartTracker.tests.cpp:<line number>: passed: m for: 2
PartTracker.tests.cpp:<line number>: passed: n for: 3
PartTracker.tests.cpp:<line number>: passed: m for: 3
PartTracker.tests.cpp:<line number>: passed: n for: 1
PartTracker.tests.cpp:<line number>: passed: m for: 3
PartTracker.tests.cpp:<line number>: passed: n for: 2
PartTracker.tests.cpp:<line number>: passed: m for: 3
PartTracker.tests.cpp:<line number>: passed: n for: 3
Misc.tests.cpp:<line number>: passed:
Misc.tests.cpp:<line number>: passed:
Misc.tests.cpp:<line number>: passed:
Exception.tests.cpp:<line number>: failed: unexpected exception with message: 'answer := 42' with 1 message: 'expected exception' Exception.tests.cpp:<line number>: failed: unexpected exception with message: 'answer := 42' with 1 message: 'expected exception'
Exception.tests.cpp:<line number>: failed: unexpected exception with message: 'answer := 42'; expression was: thisThrows() with 1 message: 'expected exception' Exception.tests.cpp:<line number>: failed: unexpected exception with message: 'answer := 42'; expression was: thisThrows() with 1 message: 'expected exception'
Exception.tests.cpp:<line number>: passed: thisThrows() with 1 message: 'answer := 42' Exception.tests.cpp:<line number>: passed: thisThrows() with 1 message: 'answer := 42'
@@ -237,6 +295,11 @@ Matchers.tests.cpp:<line number>: passed: 1, Predicate<int>(alwaysTrue, "always
Matchers.tests.cpp:<line number>: passed: 1, !Predicate<int>(alwaysFalse, "always false") for: 1 not matches predicate: "always false" Matchers.tests.cpp:<line number>: passed: 1, !Predicate<int>(alwaysFalse, "always false") for: 1 not matches predicate: "always false"
Matchers.tests.cpp:<line number>: passed: "Hello olleH", Predicate<std::string>( [] (std::string const& str) -> bool { return str.front() == str.back(); }, "First and last character should be equal") for: "Hello olleH" matches predicate: "First and last character should be equal" Matchers.tests.cpp:<line number>: passed: "Hello olleH", Predicate<std::string>( [] (std::string const& str) -> bool { return str.front() == str.back(); }, "First and last character should be equal") for: "Hello olleH" matches predicate: "First and last character should be equal"
Matchers.tests.cpp:<line number>: passed: "This wouldn't pass", !Predicate<std::string>( [] (std::string const& str) -> bool { return str.front() == str.back(); } ) for: "This wouldn't pass" not matches undescribed predicate Matchers.tests.cpp:<line number>: passed: "This wouldn't pass", !Predicate<std::string>( [] (std::string const& str) -> bool { return str.front() == str.back(); } ) for: "This wouldn't pass" not matches undescribed predicate
Compilation.tests.cpp:<line number>: passed: lhs | rhs for: Val: 1 | Val: 2
Compilation.tests.cpp:<line number>: passed: !(lhs & rhs) for: !(Val: 1 & Val: 2)
Compilation.tests.cpp:<line number>: passed: HasBitOperators{ 1 } & HasBitOperators{ 1 } for: Val: 1 & Val: 1
Compilation.tests.cpp:<line number>: passed: lhs ^ rhs for: Val: 1 ^ Val: 2
Compilation.tests.cpp:<line number>: passed: !(lhs ^ lhs) for: !(Val: 1 ^ Val: 1)
Tricky.tests.cpp:<line number>: passed: true Tricky.tests.cpp:<line number>: passed: true
Tricky.tests.cpp:<line number>: passed: true Tricky.tests.cpp:<line number>: passed: true
Tricky.tests.cpp:<line number>: passed: true Tricky.tests.cpp:<line number>: passed: true
@@ -314,6 +377,12 @@ 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(), !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>: 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>: passed: 1, !(first && second) for: 1 not ( CheckedTestingMatcher set to fail and CheckedTestingMatcher set to fail )
Matchers.tests.cpp:<line number>: passed: first.matchCalled for: true
Matchers.tests.cpp:<line number>: passed: !second.matchCalled for: true
Matchers.tests.cpp:<line number>: passed: 1, first || second for: 1 ( CheckedTestingMatcher set to succeed or CheckedTestingMatcher set to fail )
Matchers.tests.cpp:<line number>: passed: first.matchCalled for: true
Matchers.tests.cpp:<line number>: passed: !second.matchCalled for: true
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
@@ -559,6 +628,7 @@ GeneratorsImpl.tests.cpp:<line number>: passed: gen.next() for: true
GeneratorsImpl.tests.cpp:<line number>: passed: gen.get() == 3 for: 3 == 3 GeneratorsImpl.tests.cpp:<line number>: passed: gen.get() == 3 for: 3 == 3
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: filter([] (int) { return false; }, value(1)), Catch::GeneratorException GeneratorsImpl.tests.cpp:<line number>: passed: filter([] (int) { return false; }, value(1)), Catch::GeneratorException
GeneratorsImpl.tests.cpp:<line number>: passed: filter( []( int ) { return false; }, values( { 1, 2, 3 } ) ), Catch::GeneratorException
GeneratorsImpl.tests.cpp:<line number>: passed: gen.get() == 1 for: 1 == 1 GeneratorsImpl.tests.cpp:<line number>: passed: gen.get() == 1 for: 1 == 1
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
@@ -777,6 +847,10 @@ Matchers.tests.cpp:<line number>: passed: testStringForMatching(), (Contains("st
Matchers.tests.cpp:<line number>: failed: testStringForMatching(), (Contains("string") || Contains("different")) && Contains("random") for: "this string contains 'abc' as a substring" ( ( contains: "string" or contains: "different" ) and contains: "random" ) Matchers.tests.cpp:<line number>: failed: testStringForMatching(), (Contains("string") || Contains("different")) && Contains("random") for: "this string contains 'abc' as a substring" ( ( contains: "string" or contains: "different" ) and contains: "random" )
Matchers.tests.cpp:<line number>: passed: testStringForMatching(), !Contains("different") for: "this string contains 'abc' as a substring" not contains: "different" Matchers.tests.cpp:<line number>: passed: testStringForMatching(), !Contains("different") for: "this string contains 'abc' as a substring" not contains: "different"
Matchers.tests.cpp:<line number>: failed: testStringForMatching(), !Contains("substring") for: "this string contains 'abc' as a substring" not contains: "substring" Matchers.tests.cpp:<line number>: failed: testStringForMatching(), !Contains("substring") for: "this string contains 'abc' as a substring" not contains: "substring"
Condition.tests.cpp:<line number>: failed: explicitly
Condition.tests.cpp:<line number>: failed: explicitly
Condition.tests.cpp:<line number>: failed: explicitly
Condition.tests.cpp:<line number>: failed: explicitly
Exception.tests.cpp:<line number>: passed: thisThrows(), "expected exception" for: "expected exception" equals: "expected exception" Exception.tests.cpp:<line number>: passed: thisThrows(), "expected exception" for: "expected exception" equals: "expected exception"
Exception.tests.cpp:<line number>: failed: thisThrows(), "should fail" for: "expected exception" equals: "should fail" Exception.tests.cpp:<line number>: failed: thisThrows(), "should fail" for: "expected exception" equals: "should fail"
Generators.tests.cpp:<line number>: passed: values > -6 for: 3 > -6 Generators.tests.cpp:<line number>: passed: values > -6 for: 3 > -6
@@ -1134,6 +1208,7 @@ CmdLine.tests.cpp:<line number>: passed: config.benchmarkWarmupTime == 10 for: 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: 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
ToString.tests.cpp:<line number>: passed: Catch::Detail::stringify(UsesSentinel{}) == "{ }" for: "{ }" == "{ }"
Decomposition.tests.cpp:<line number>: failed: truthy(false) for: Hey, its truthy! Decomposition.tests.cpp:<line number>: failed: truthy(false) for: Hey, its truthy!
Matchers.tests.cpp:<line number>: failed: testStringForMatching(), Matches("this STRING contains 'abc' as a substring") for: "this string contains 'abc' as a substring" matches "this STRING contains 'abc' as a substring" case sensitively Matchers.tests.cpp:<line number>: failed: testStringForMatching(), Matches("this STRING contains 'abc' as a substring") for: "this string contains 'abc' as a substring" matches "this STRING contains 'abc' as a substring" case sensitively
Matchers.tests.cpp:<line number>: failed: testStringForMatching(), Matches("contains 'abc' as a substring") for: "this string contains 'abc' as a substring" matches "contains 'abc' as a substring" case sensitively Matchers.tests.cpp:<line number>: failed: testStringForMatching(), Matches("contains 'abc' as a substring") for: "this string contains 'abc' as a substring" matches "contains 'abc' as a substring" case sensitively
@@ -1519,6 +1594,7 @@ Approx.tests.cpp:<line number>: passed: approx( d ) != 1.25 for: Approx( 1.23 )
VariadicMacros.tests.cpp:<line number>: passed: with 1 message: 'no assertions' VariadicMacros.tests.cpp:<line number>: passed: with 1 message: 'no assertions'
Matchers.tests.cpp:<line number>: passed: empty, Approx(empty) for: { } is approx: { } Matchers.tests.cpp:<line number>: passed: empty, Approx(empty) for: { } is approx: { }
Matchers.tests.cpp:<line number>: passed: v1, Approx(v1) for: { 1.0, 2.0, 3.0 } is approx: { 1.0, 2.0, 3.0 } Matchers.tests.cpp:<line number>: passed: v1, Approx(v1) for: { 1.0, 2.0, 3.0 } is approx: { 1.0, 2.0, 3.0 }
Matchers.tests.cpp:<line number>: passed: v1, Approx<double>({ 1., 2., 3. }) for: { 1.0, 2.0, 3.0 } is approx: { 1.0, 2.0, 3.0 }
Matchers.tests.cpp:<line number>: passed: v1, !Approx(temp) for: { 1.0, 2.0, 3.0 } not is approx: { 1.0, 2.0, 3.0, 4.0 } Matchers.tests.cpp:<line number>: passed: v1, !Approx(temp) for: { 1.0, 2.0, 3.0 } not is approx: { 1.0, 2.0, 3.0, 4.0 }
Matchers.tests.cpp:<line number>: passed: v1, !Approx(v2) for: { 1.0, 2.0, 3.0 } not is approx: { 1.5, 2.5, 3.5 } Matchers.tests.cpp:<line number>: passed: v1, !Approx(v2) for: { 1.0, 2.0, 3.0 } not is approx: { 1.5, 2.5, 3.5 }
Matchers.tests.cpp:<line number>: passed: v1, Approx(v2).margin(0.5) for: { 1.0, 2.0, 3.0 } is approx: { 1.5, 2.5, 3.5 } Matchers.tests.cpp:<line number>: passed: v1, Approx(v2).margin(0.5) for: { 1.0, 2.0, 3.0 } is approx: { 1.5, 2.5, 3.5 }
@@ -1528,18 +1604,29 @@ Matchers.tests.cpp:<line number>: failed: empty, Approx(t1) for: { } is approx:
Matchers.tests.cpp:<line number>: failed: v1, Approx(v2) for: { 2.0, 4.0, 6.0 } is approx: { 1.0, 3.0, 5.0 } Matchers.tests.cpp:<line number>: failed: v1, Approx(v2) for: { 2.0, 4.0, 6.0 } is approx: { 1.0, 3.0, 5.0 }
Matchers.tests.cpp:<line number>: passed: v, VectorContains(1) for: { 1, 2, 3 } Contains: 1 Matchers.tests.cpp:<line number>: passed: v, VectorContains(1) for: { 1, 2, 3 } Contains: 1
Matchers.tests.cpp:<line number>: passed: v, VectorContains(2) for: { 1, 2, 3 } Contains: 2 Matchers.tests.cpp:<line number>: passed: v, VectorContains(2) for: { 1, 2, 3 } Contains: 2
Matchers.tests.cpp:<line number>: passed: v5, (VectorContains<int, CustomAllocator<int>>(2)) for: { 1, 2, 3 } Contains: 2
Matchers.tests.cpp:<line number>: passed: v, Contains(v2) for: { 1, 2, 3 } Contains: { 1, 2 } Matchers.tests.cpp:<line number>: passed: v, Contains(v2) for: { 1, 2, 3 } Contains: { 1, 2 }
Matchers.tests.cpp:<line number>: passed: v, Contains<int>({ 1, 2 }) for: { 1, 2, 3 } Contains: { 1, 2 }
Matchers.tests.cpp:<line number>: passed: v5, (Contains<int, std::allocator<int>, CustomAllocator<int>>(v2)) for: { 1, 2, 3 } Contains: { 1, 2 }
Matchers.tests.cpp:<line number>: passed: v, Contains(v2) for: { 1, 2, 3 } Contains: { 1, 2, 3 } Matchers.tests.cpp:<line number>: passed: v, Contains(v2) for: { 1, 2, 3 } Contains: { 1, 2, 3 }
Matchers.tests.cpp:<line number>: passed: v, Contains(empty) for: { 1, 2, 3 } Contains: { } Matchers.tests.cpp:<line number>: passed: v, Contains(empty) for: { 1, 2, 3 } Contains: { }
Matchers.tests.cpp:<line number>: passed: empty, Contains(empty) for: { } Contains: { } Matchers.tests.cpp:<line number>: passed: empty, Contains(empty) for: { } Contains: { }
Matchers.tests.cpp:<line number>: passed: v5, (Contains<int, std::allocator<int>, CustomAllocator<int>>(v2)) for: { 1, 2, 3 } Contains: { 1, 2, 3 }
Matchers.tests.cpp:<line number>: passed: v5, Contains(v6) for: { 1, 2, 3 } Contains: { 1, 2 }
Matchers.tests.cpp:<line number>: passed: v, VectorContains(1) && VectorContains(2) for: { 1, 2, 3 } ( Contains: 1 and Contains: 2 ) Matchers.tests.cpp:<line number>: passed: v, VectorContains(1) && VectorContains(2) for: { 1, 2, 3 } ( Contains: 1 and Contains: 2 )
Matchers.tests.cpp:<line number>: passed: v, Equals(v) for: { 1, 2, 3 } Equals: { 1, 2, 3 } Matchers.tests.cpp:<line number>: passed: v, Equals(v) for: { 1, 2, 3 } Equals: { 1, 2, 3 }
Matchers.tests.cpp:<line number>: passed: empty, Equals(empty) for: { } Equals: { } Matchers.tests.cpp:<line number>: passed: empty, Equals(empty) for: { } Equals: { }
Matchers.tests.cpp:<line number>: passed: v, Equals<int>({ 1, 2, 3 }) for: { 1, 2, 3 } Equals: { 1, 2, 3 }
Matchers.tests.cpp:<line number>: passed: v, Equals(v2) for: { 1, 2, 3 } Equals: { 1, 2, 3 } Matchers.tests.cpp:<line number>: passed: v, Equals(v2) for: { 1, 2, 3 } Equals: { 1, 2, 3 }
Matchers.tests.cpp:<line number>: passed: v5, (Equals<int, std::allocator<int>, CustomAllocator<int>>(v2)) for: { 1, 2, 3 } Equals: { 1, 2, 3 }
Matchers.tests.cpp:<line number>: passed: v5, Equals(v6) for: { 1, 2, 3 } Equals: { 1, 2, 3 }
Matchers.tests.cpp:<line number>: passed: v, UnorderedEquals(v) for: { 1, 2, 3 } UnorderedEquals: { 1, 2, 3 } Matchers.tests.cpp:<line number>: passed: v, UnorderedEquals(v) for: { 1, 2, 3 } UnorderedEquals: { 1, 2, 3 }
Matchers.tests.cpp:<line number>: passed: v, UnorderedEquals<int>({ 3, 2, 1 }) for: { 1, 2, 3 } UnorderedEquals: { 3, 2, 1 }
Matchers.tests.cpp:<line number>: passed: empty, UnorderedEquals(empty) for: { } UnorderedEquals: { } Matchers.tests.cpp:<line number>: passed: empty, UnorderedEquals(empty) for: { } UnorderedEquals: { }
Matchers.tests.cpp:<line number>: passed: permuted, UnorderedEquals(v) for: { 1, 3, 2 } UnorderedEquals: { 1, 2, 3 } Matchers.tests.cpp:<line number>: passed: permuted, UnorderedEquals(v) for: { 1, 3, 2 } UnorderedEquals: { 1, 2, 3 }
Matchers.tests.cpp:<line number>: passed: permuted, UnorderedEquals(v) for: { 2, 3, 1 } UnorderedEquals: { 1, 2, 3 } Matchers.tests.cpp:<line number>: passed: permuted, UnorderedEquals(v) for: { 2, 3, 1 } UnorderedEquals: { 1, 2, 3 }
Matchers.tests.cpp:<line number>: passed: v5, (UnorderedEquals<int, std::allocator<int>, CustomAllocator<int>>(permuted)) for: { 1, 2, 3 } UnorderedEquals: { 2, 3, 1 }
Matchers.tests.cpp:<line number>: passed: v5_permuted, UnorderedEquals(v5) for: { 1, 3, 2 } UnorderedEquals: { 1, 2, 3 }
Matchers.tests.cpp:<line number>: failed: v, VectorContains(-1) for: { 1, 2, 3 } Contains: -1 Matchers.tests.cpp:<line number>: failed: v, VectorContains(-1) for: { 1, 2, 3 } Contains: -1
Matchers.tests.cpp:<line number>: failed: empty, VectorContains(1) for: { } Contains: 1 Matchers.tests.cpp:<line number>: failed: empty, VectorContains(1) for: { } Contains: 1
Matchers.tests.cpp:<line number>: failed: empty, Contains(v) for: { } Contains: { 1, 2, 3 } Matchers.tests.cpp:<line number>: failed: empty, Contains(v) for: { } Contains: { 1, 2, 3 }

View File

@@ -694,6 +694,46 @@ Matchers.tests.cpp:<line number>: FAILED:
with expansion: with expansion:
"this string contains 'abc' as a substring" not contains: "substring" "this string contains 'abc' as a substring" not contains: "substring"
-------------------------------------------------------------------------------
Mayfail test case with nested sections
A
1
-------------------------------------------------------------------------------
Condition.tests.cpp:<line number>
...............................................................................
Condition.tests.cpp:<line number>: FAILED:
-------------------------------------------------------------------------------
Mayfail test case with nested sections
A
2
-------------------------------------------------------------------------------
Condition.tests.cpp:<line number>
...............................................................................
Condition.tests.cpp:<line number>: FAILED:
-------------------------------------------------------------------------------
Mayfail test case with nested sections
B
1
-------------------------------------------------------------------------------
Condition.tests.cpp:<line number>
...............................................................................
Condition.tests.cpp:<line number>: FAILED:
-------------------------------------------------------------------------------
Mayfail test case with nested sections
B
2
-------------------------------------------------------------------------------
Condition.tests.cpp:<line number>
...............................................................................
Condition.tests.cpp:<line number>: FAILED:
------------------------------------------------------------------------------- -------------------------------------------------------------------------------
Mismatching exception messages failing the test Mismatching exception messages failing the test
------------------------------------------------------------------------------- -------------------------------------------------------------------------------
@@ -1380,6 +1420,6 @@ due to unexpected exception with message:
Why would you throw a std::string? Why would you throw a std::string?
=============================================================================== ===============================================================================
test cases: 307 | 233 passed | 70 failed | 4 failed as expected test cases: 323 | 248 passed | 70 failed | 5 failed as expected
assertions: 1677 | 1525 passed | 131 failed | 21 failed as expected assertions: 1764 | 1608 passed | 131 failed | 25 failed as expected

View File

@@ -188,6 +188,569 @@ Compilation.tests.cpp:<line number>: PASSED:
with expansion: with expansion:
true true
-------------------------------------------------------------------------------
#1905 -- test spec parser properly clears internal state between compound tests
-------------------------------------------------------------------------------
CmdLine.tests.cpp:<line number>
...............................................................................
CmdLine.tests.cpp:<line number>: PASSED:
REQUIRE( spec.matches(fakeTestCase("spec . char")) )
with expansion:
true
CmdLine.tests.cpp:<line number>: PASSED:
REQUIRE( spec.matches(fakeTestCase("spec , char")) )
with expansion:
true
CmdLine.tests.cpp:<line number>: PASSED:
REQUIRE_FALSE( spec.matches(fakeTestCase(R"(spec \, char)")) )
with expansion:
!false
-------------------------------------------------------------------------------
#1912 -- test spec parser handles escaping
Various parentheses
-------------------------------------------------------------------------------
CmdLine.tests.cpp:<line number>
...............................................................................
CmdLine.tests.cpp:<line number>: PASSED:
REQUIRE( spec.matches(fakeTestCase(R"(spec {a} char)")) )
with expansion:
true
CmdLine.tests.cpp:<line number>: PASSED:
REQUIRE( spec.matches(fakeTestCase(R"(spec [a] char)")) )
with expansion:
true
CmdLine.tests.cpp:<line number>: PASSED:
REQUIRE_FALSE( spec.matches(fakeTestCase("differs but has similar tag", "[a]")) )
with expansion:
!false
-------------------------------------------------------------------------------
#1912 -- test spec parser handles escaping
backslash in test name
-------------------------------------------------------------------------------
CmdLine.tests.cpp:<line number>
...............................................................................
CmdLine.tests.cpp:<line number>: PASSED:
REQUIRE( spec.matches(fakeTestCase(R"(spec \ char)")) )
with expansion:
true
-------------------------------------------------------------------------------
#1913 - GENERATE inside a for loop should not keep recreating the generator
-------------------------------------------------------------------------------
Generators.tests.cpp:<line number>
...............................................................................
Generators.tests.cpp:<line number>: PASSED:
REQUIRE( counter < 7 )
with expansion:
3 < 7
-------------------------------------------------------------------------------
#1913 - GENERATE inside a for loop should not keep recreating the generator
-------------------------------------------------------------------------------
Generators.tests.cpp:<line number>
...............................................................................
Generators.tests.cpp:<line number>: PASSED:
REQUIRE( counter < 7 )
with expansion:
6 < 7
-------------------------------------------------------------------------------
#1913 - GENERATEs can share a line
-------------------------------------------------------------------------------
Generators.tests.cpp:<line number>
...............................................................................
Generators.tests.cpp:<line number>: PASSED:
REQUIRE( i != j )
with expansion:
1 != 3
-------------------------------------------------------------------------------
#1913 - GENERATEs can share a line
-------------------------------------------------------------------------------
Generators.tests.cpp:<line number>
...............................................................................
Generators.tests.cpp:<line number>: PASSED:
REQUIRE( i != j )
with expansion:
1 != 4
-------------------------------------------------------------------------------
#1913 - GENERATEs can share a line
-------------------------------------------------------------------------------
Generators.tests.cpp:<line number>
...............................................................................
Generators.tests.cpp:<line number>: PASSED:
REQUIRE( i != j )
with expansion:
2 != 3
-------------------------------------------------------------------------------
#1913 - GENERATEs can share a line
-------------------------------------------------------------------------------
Generators.tests.cpp:<line number>
...............................................................................
Generators.tests.cpp:<line number>: PASSED:
REQUIRE( i != j )
with expansion:
2 != 4
-------------------------------------------------------------------------------
#1938 - GENERATE after a section
A
-------------------------------------------------------------------------------
PartTracker.tests.cpp:<line number>
...............................................................................
PartTracker.tests.cpp:<line number>: PASSED:
with message:
A
-------------------------------------------------------------------------------
#1938 - GENERATE after a section
B
-------------------------------------------------------------------------------
PartTracker.tests.cpp:<line number>
...............................................................................
PartTracker.tests.cpp:<line number>: PASSED:
REQUIRE( m )
with expansion:
1
-------------------------------------------------------------------------------
#1938 - GENERATE after a section
B
-------------------------------------------------------------------------------
PartTracker.tests.cpp:<line number>
...............................................................................
PartTracker.tests.cpp:<line number>: PASSED:
REQUIRE( m )
with expansion:
2
-------------------------------------------------------------------------------
#1938 - GENERATE after a section
B
-------------------------------------------------------------------------------
PartTracker.tests.cpp:<line number>
...............................................................................
PartTracker.tests.cpp:<line number>: PASSED:
REQUIRE( m )
with expansion:
3
-------------------------------------------------------------------------------
#1938 - Section followed by flat generate
A
-------------------------------------------------------------------------------
PartTracker.tests.cpp:<line number>
...............................................................................
PartTracker.tests.cpp:<line number>: PASSED:
REQUIRE( 1 )
-------------------------------------------------------------------------------
#1938 - Section followed by flat generate
-------------------------------------------------------------------------------
PartTracker.tests.cpp:<line number>
...............................................................................
PartTracker.tests.cpp:<line number>: PASSED:
REQUIRE( m )
with expansion:
2
-------------------------------------------------------------------------------
#1938 - Section followed by flat generate
-------------------------------------------------------------------------------
PartTracker.tests.cpp:<line number>
...............................................................................
PartTracker.tests.cpp:<line number>: PASSED:
REQUIRE( m )
with expansion:
3
-------------------------------------------------------------------------------
#1938 - flat generate
-------------------------------------------------------------------------------
PartTracker.tests.cpp:<line number>
...............................................................................
PartTracker.tests.cpp:<line number>: PASSED:
REQUIRE( m )
with expansion:
1
-------------------------------------------------------------------------------
#1938 - flat generate
-------------------------------------------------------------------------------
PartTracker.tests.cpp:<line number>
...............................................................................
PartTracker.tests.cpp:<line number>: PASSED:
REQUIRE( m )
with expansion:
2
-------------------------------------------------------------------------------
#1938 - flat generate
-------------------------------------------------------------------------------
PartTracker.tests.cpp:<line number>
...............................................................................
PartTracker.tests.cpp:<line number>: PASSED:
REQUIRE( m )
with expansion:
3
-------------------------------------------------------------------------------
#1938 - mixed sections and generates
A
-------------------------------------------------------------------------------
PartTracker.tests.cpp:<line number>
...............................................................................
PartTracker.tests.cpp:<line number>: PASSED:
with message:
A
-------------------------------------------------------------------------------
#1938 - mixed sections and generates
-------------------------------------------------------------------------------
PartTracker.tests.cpp:<line number>
...............................................................................
PartTracker.tests.cpp:<line number>: PASSED:
with messages:
i := 1
j := 3
k := 5
-------------------------------------------------------------------------------
#1938 - mixed sections and generates
B
-------------------------------------------------------------------------------
PartTracker.tests.cpp:<line number>
...............................................................................
PartTracker.tests.cpp:<line number>: PASSED:
with message:
B
-------------------------------------------------------------------------------
#1938 - mixed sections and generates
-------------------------------------------------------------------------------
PartTracker.tests.cpp:<line number>
...............................................................................
PartTracker.tests.cpp:<line number>: PASSED:
with messages:
i := 1
j := 3
k := 6
-------------------------------------------------------------------------------
#1938 - mixed sections and generates
B
-------------------------------------------------------------------------------
PartTracker.tests.cpp:<line number>
...............................................................................
PartTracker.tests.cpp:<line number>: PASSED:
with message:
B
-------------------------------------------------------------------------------
#1938 - mixed sections and generates
-------------------------------------------------------------------------------
PartTracker.tests.cpp:<line number>
...............................................................................
PartTracker.tests.cpp:<line number>: PASSED:
with messages:
i := 1
j := 4
k := 5
-------------------------------------------------------------------------------
#1938 - mixed sections and generates
-------------------------------------------------------------------------------
PartTracker.tests.cpp:<line number>
...............................................................................
PartTracker.tests.cpp:<line number>: PASSED:
with messages:
i := 1
j := 4
k := 6
-------------------------------------------------------------------------------
#1938 - mixed sections and generates
A
-------------------------------------------------------------------------------
PartTracker.tests.cpp:<line number>
...............................................................................
PartTracker.tests.cpp:<line number>: PASSED:
with message:
A
-------------------------------------------------------------------------------
#1938 - mixed sections and generates
-------------------------------------------------------------------------------
PartTracker.tests.cpp:<line number>
...............................................................................
PartTracker.tests.cpp:<line number>: PASSED:
with messages:
i := 2
j := 3
k := 5
-------------------------------------------------------------------------------
#1938 - mixed sections and generates
B
-------------------------------------------------------------------------------
PartTracker.tests.cpp:<line number>
...............................................................................
PartTracker.tests.cpp:<line number>: PASSED:
with message:
B
-------------------------------------------------------------------------------
#1938 - mixed sections and generates
-------------------------------------------------------------------------------
PartTracker.tests.cpp:<line number>
...............................................................................
PartTracker.tests.cpp:<line number>: PASSED:
with messages:
i := 2
j := 3
k := 6
-------------------------------------------------------------------------------
#1938 - mixed sections and generates
B
-------------------------------------------------------------------------------
PartTracker.tests.cpp:<line number>
...............................................................................
PartTracker.tests.cpp:<line number>: PASSED:
with message:
B
-------------------------------------------------------------------------------
#1938 - mixed sections and generates
-------------------------------------------------------------------------------
PartTracker.tests.cpp:<line number>
...............................................................................
PartTracker.tests.cpp:<line number>: PASSED:
with messages:
i := 2
j := 4
k := 5
-------------------------------------------------------------------------------
#1938 - mixed sections and generates
-------------------------------------------------------------------------------
PartTracker.tests.cpp:<line number>
...............................................................................
PartTracker.tests.cpp:<line number>: PASSED:
with messages:
i := 2
j := 4
k := 6
-------------------------------------------------------------------------------
#1938 - nested generate
-------------------------------------------------------------------------------
PartTracker.tests.cpp:<line number>
...............................................................................
PartTracker.tests.cpp:<line number>: PASSED:
REQUIRE( m )
with expansion:
1
PartTracker.tests.cpp:<line number>: PASSED:
REQUIRE( n )
with expansion:
1
-------------------------------------------------------------------------------
#1938 - nested generate
-------------------------------------------------------------------------------
PartTracker.tests.cpp:<line number>
...............................................................................
PartTracker.tests.cpp:<line number>: PASSED:
REQUIRE( m )
with expansion:
1
PartTracker.tests.cpp:<line number>: PASSED:
REQUIRE( n )
with expansion:
2
-------------------------------------------------------------------------------
#1938 - nested generate
-------------------------------------------------------------------------------
PartTracker.tests.cpp:<line number>
...............................................................................
PartTracker.tests.cpp:<line number>: PASSED:
REQUIRE( m )
with expansion:
1
PartTracker.tests.cpp:<line number>: PASSED:
REQUIRE( n )
with expansion:
3
-------------------------------------------------------------------------------
#1938 - nested generate
-------------------------------------------------------------------------------
PartTracker.tests.cpp:<line number>
...............................................................................
PartTracker.tests.cpp:<line number>: PASSED:
REQUIRE( m )
with expansion:
2
PartTracker.tests.cpp:<line number>: PASSED:
REQUIRE( n )
with expansion:
1
-------------------------------------------------------------------------------
#1938 - nested generate
-------------------------------------------------------------------------------
PartTracker.tests.cpp:<line number>
...............................................................................
PartTracker.tests.cpp:<line number>: PASSED:
REQUIRE( m )
with expansion:
2
PartTracker.tests.cpp:<line number>: PASSED:
REQUIRE( n )
with expansion:
2
-------------------------------------------------------------------------------
#1938 - nested generate
-------------------------------------------------------------------------------
PartTracker.tests.cpp:<line number>
...............................................................................
PartTracker.tests.cpp:<line number>: PASSED:
REQUIRE( m )
with expansion:
2
PartTracker.tests.cpp:<line number>: PASSED:
REQUIRE( n )
with expansion:
3
-------------------------------------------------------------------------------
#1938 - nested generate
-------------------------------------------------------------------------------
PartTracker.tests.cpp:<line number>
...............................................................................
PartTracker.tests.cpp:<line number>: PASSED:
REQUIRE( m )
with expansion:
3
PartTracker.tests.cpp:<line number>: PASSED:
REQUIRE( n )
with expansion:
1
-------------------------------------------------------------------------------
#1938 - nested generate
-------------------------------------------------------------------------------
PartTracker.tests.cpp:<line number>
...............................................................................
PartTracker.tests.cpp:<line number>: PASSED:
REQUIRE( m )
with expansion:
3
PartTracker.tests.cpp:<line number>: PASSED:
REQUIRE( n )
with expansion:
2
-------------------------------------------------------------------------------
#1938 - nested generate
-------------------------------------------------------------------------------
PartTracker.tests.cpp:<line number>
...............................................................................
PartTracker.tests.cpp:<line number>: PASSED:
REQUIRE( m )
with expansion:
3
PartTracker.tests.cpp:<line number>: PASSED:
REQUIRE( n )
with expansion:
3
-------------------------------------------------------------------------------
#1954 - 7 arg template test case sig compiles - 1, 1, 1, 1, 1, 0, 0
-------------------------------------------------------------------------------
Misc.tests.cpp:<line number>
...............................................................................
Misc.tests.cpp:<line number>: PASSED:
-------------------------------------------------------------------------------
#1954 - 7 arg template test case sig compiles - 5, 1, 1, 1, 1, 0, 0
-------------------------------------------------------------------------------
Misc.tests.cpp:<line number>
...............................................................................
Misc.tests.cpp:<line number>: PASSED:
-------------------------------------------------------------------------------
#1954 - 7 arg template test case sig compiles - 5, 3, 1, 1, 1, 0, 0
-------------------------------------------------------------------------------
Misc.tests.cpp:<line number>
...............................................................................
Misc.tests.cpp:<line number>: PASSED:
------------------------------------------------------------------------------- -------------------------------------------------------------------------------
#748 - captures with unexpected exceptions #748 - captures with unexpected exceptions
outside assertions outside assertions
@@ -1879,6 +2442,37 @@ Matchers.tests.cpp:<line number>: PASSED:
with expansion: with expansion:
"This wouldn't pass" not matches undescribed predicate "This wouldn't pass" not matches undescribed predicate
-------------------------------------------------------------------------------
Assertion macros support bit operators and bool conversions
-------------------------------------------------------------------------------
Compilation.tests.cpp:<line number>
...............................................................................
Compilation.tests.cpp:<line number>: PASSED:
REQUIRE( lhs | rhs )
with expansion:
Val: 1 | Val: 2
Compilation.tests.cpp:<line number>: PASSED:
REQUIRE_FALSE( lhs & rhs )
with expansion:
!(Val: 1 & Val: 2)
Compilation.tests.cpp:<line number>: PASSED:
REQUIRE( HasBitOperators{ 1 } & HasBitOperators{ 1 } )
with expansion:
Val: 1 & Val: 1
Compilation.tests.cpp:<line number>: PASSED:
REQUIRE( lhs ^ rhs )
with expansion:
Val: 1 ^ Val: 2
Compilation.tests.cpp:<line number>: PASSED:
REQUIRE_FALSE( lhs ^ lhs )
with expansion:
!(Val: 1 ^ Val: 1)
------------------------------------------------------------------------------- -------------------------------------------------------------------------------
Assertions then sections Assertions then sections
------------------------------------------------------------------------------- -------------------------------------------------------------------------------
@@ -2408,6 +3002,52 @@ with expansion:
"some completely different text that contains one common word" ( contains: "some completely different text that contains one common word" ( contains:
"string" or contains: "random" or contains: "different" ) "string" or contains: "random" or contains: "different" )
-------------------------------------------------------------------------------
Composed matchers shortcircuit
&&
-------------------------------------------------------------------------------
Matchers.tests.cpp:<line number>
...............................................................................
Matchers.tests.cpp:<line number>: PASSED:
CHECK_THAT( 1, !(first && second) )
with expansion:
1 not ( CheckedTestingMatcher set to fail and CheckedTestingMatcher set to
fail )
Matchers.tests.cpp:<line number>: PASSED:
REQUIRE( first.matchCalled )
with expansion:
true
Matchers.tests.cpp:<line number>: PASSED:
REQUIRE( !second.matchCalled )
with expansion:
true
-------------------------------------------------------------------------------
Composed matchers shortcircuit
||
-------------------------------------------------------------------------------
Matchers.tests.cpp:<line number>
...............................................................................
Matchers.tests.cpp:<line number>: PASSED:
CHECK_THAT( 1, first || second )
with expansion:
1 ( CheckedTestingMatcher set to succeed or CheckedTestingMatcher set to fail
)
Matchers.tests.cpp:<line number>: PASSED:
REQUIRE( first.matchCalled )
with expansion:
true
Matchers.tests.cpp:<line number>: PASSED:
REQUIRE( !second.matchCalled )
with expansion:
true
------------------------------------------------------------------------------- -------------------------------------------------------------------------------
Contains string matcher Contains string matcher
------------------------------------------------------------------------------- -------------------------------------------------------------------------------
@@ -4328,6 +4968,9 @@ with expansion:
GeneratorsImpl.tests.cpp:<line number>: PASSED: GeneratorsImpl.tests.cpp:<line number>: PASSED:
REQUIRE_THROWS_AS( filter([] (int) { return false; }, value(1)), Catch::GeneratorException ) REQUIRE_THROWS_AS( filter([] (int) { return false; }, value(1)), Catch::GeneratorException )
GeneratorsImpl.tests.cpp:<line number>: PASSED:
REQUIRE_THROWS_AS( filter( []( int ) { return false; }, values( { 1, 2, 3 } ) ), Catch::GeneratorException )
------------------------------------------------------------------------------- -------------------------------------------------------------------------------
Generators internals Generators internals
Take generator Take generator
@@ -5852,6 +6495,46 @@ Matchers.tests.cpp:<line number>: FAILED:
with expansion: with expansion:
"this string contains 'abc' as a substring" not contains: "substring" "this string contains 'abc' as a substring" not contains: "substring"
-------------------------------------------------------------------------------
Mayfail test case with nested sections
A
1
-------------------------------------------------------------------------------
Condition.tests.cpp:<line number>
...............................................................................
Condition.tests.cpp:<line number>: FAILED:
-------------------------------------------------------------------------------
Mayfail test case with nested sections
A
2
-------------------------------------------------------------------------------
Condition.tests.cpp:<line number>
...............................................................................
Condition.tests.cpp:<line number>: FAILED:
-------------------------------------------------------------------------------
Mayfail test case with nested sections
B
1
-------------------------------------------------------------------------------
Condition.tests.cpp:<line number>
...............................................................................
Condition.tests.cpp:<line number>: FAILED:
-------------------------------------------------------------------------------
Mayfail test case with nested sections
B
2
-------------------------------------------------------------------------------
Condition.tests.cpp:<line number>
...............................................................................
Condition.tests.cpp:<line number>: FAILED:
------------------------------------------------------------------------------- -------------------------------------------------------------------------------
Mismatching exception messages failing the test Mismatching exception messages failing the test
------------------------------------------------------------------------------- -------------------------------------------------------------------------------
@@ -8255,6 +8938,17 @@ Misc.tests.cpp:<line number>: PASSED:
with expansion: with expansion:
1 >= 1 1 >= 1
-------------------------------------------------------------------------------
Range type with sentinel
-------------------------------------------------------------------------------
ToString.tests.cpp:<line number>
...............................................................................
ToString.tests.cpp:<line number>: PASSED:
CHECK( Catch::Detail::stringify(UsesSentinel{}) == "{ }" )
with expansion:
"{ }" == "{ }"
------------------------------------------------------------------------------- -------------------------------------------------------------------------------
Reconstruction should be based on stringification: #914 Reconstruction should be based on stringification: #914
------------------------------------------------------------------------------- -------------------------------------------------------------------------------
@@ -11101,6 +11795,11 @@ Matchers.tests.cpp:<line number>: PASSED:
with expansion: with expansion:
{ 1.0, 2.0, 3.0 } is approx: { 1.0, 2.0, 3.0 } { 1.0, 2.0, 3.0 } is approx: { 1.0, 2.0, 3.0 }
Matchers.tests.cpp:<line number>: PASSED:
REQUIRE_THAT( v1, Approx<double>({ 1., 2., 3. }) )
with expansion:
{ 1.0, 2.0, 3.0 } is approx: { 1.0, 2.0, 3.0 }
------------------------------------------------------------------------------- -------------------------------------------------------------------------------
Vector Approx matcher Vector Approx matcher
Vectors with elements Vectors with elements
@@ -11183,6 +11882,11 @@ Matchers.tests.cpp:<line number>: PASSED:
with expansion: with expansion:
{ 1, 2, 3 } Contains: 2 { 1, 2, 3 } Contains: 2
Matchers.tests.cpp:<line number>: PASSED:
CHECK_THAT( v5, (VectorContains<int, CustomAllocator<int>>(2)) )
with expansion:
{ 1, 2, 3 } Contains: 2
------------------------------------------------------------------------------- -------------------------------------------------------------------------------
Vector matchers Vector matchers
Contains (vector) Contains (vector)
@@ -11195,6 +11899,16 @@ Matchers.tests.cpp:<line number>: PASSED:
with expansion: with expansion:
{ 1, 2, 3 } Contains: { 1, 2 } { 1, 2, 3 } Contains: { 1, 2 }
Matchers.tests.cpp:<line number>: PASSED:
CHECK_THAT( v, Contains<int>({ 1, 2 }) )
with expansion:
{ 1, 2, 3 } Contains: { 1, 2 }
Matchers.tests.cpp:<line number>: PASSED:
CHECK_THAT( v5, (Contains<int, std::allocator<int>, CustomAllocator<int>>(v2)) )
with expansion:
{ 1, 2, 3 } Contains: { 1, 2 }
Matchers.tests.cpp:<line number>: PASSED: Matchers.tests.cpp:<line number>: PASSED:
CHECK_THAT( v, Contains(v2) ) CHECK_THAT( v, Contains(v2) )
with expansion: with expansion:
@@ -11210,6 +11924,16 @@ Matchers.tests.cpp:<line number>: PASSED:
with expansion: with expansion:
{ } Contains: { } { } Contains: { }
Matchers.tests.cpp:<line number>: PASSED:
CHECK_THAT( v5, (Contains<int, std::allocator<int>, CustomAllocator<int>>(v2)) )
with expansion:
{ 1, 2, 3 } Contains: { 1, 2, 3 }
Matchers.tests.cpp:<line number>: PASSED:
CHECK_THAT( v5, Contains(v6) )
with expansion:
{ 1, 2, 3 } Contains: { 1, 2 }
------------------------------------------------------------------------------- -------------------------------------------------------------------------------
Vector matchers Vector matchers
Contains (element), composed Contains (element), composed
@@ -11239,11 +11963,26 @@ Matchers.tests.cpp:<line number>: PASSED:
with expansion: with expansion:
{ } Equals: { } { } Equals: { }
Matchers.tests.cpp:<line number>: PASSED:
CHECK_THAT( v, Equals<int>({ 1, 2, 3 }) )
with expansion:
{ 1, 2, 3 } Equals: { 1, 2, 3 }
Matchers.tests.cpp:<line number>: PASSED: Matchers.tests.cpp:<line number>: PASSED:
CHECK_THAT( v, Equals(v2) ) CHECK_THAT( v, Equals(v2) )
with expansion: with expansion:
{ 1, 2, 3 } Equals: { 1, 2, 3 } { 1, 2, 3 } Equals: { 1, 2, 3 }
Matchers.tests.cpp:<line number>: PASSED:
CHECK_THAT( v5, (Equals<int, std::allocator<int>, CustomAllocator<int>>(v2)) )
with expansion:
{ 1, 2, 3 } Equals: { 1, 2, 3 }
Matchers.tests.cpp:<line number>: PASSED:
CHECK_THAT( v5, Equals(v6) )
with expansion:
{ 1, 2, 3 } Equals: { 1, 2, 3 }
------------------------------------------------------------------------------- -------------------------------------------------------------------------------
Vector matchers Vector matchers
UnorderedEquals UnorderedEquals
@@ -11256,6 +11995,11 @@ Matchers.tests.cpp:<line number>: PASSED:
with expansion: with expansion:
{ 1, 2, 3 } UnorderedEquals: { 1, 2, 3 } { 1, 2, 3 } UnorderedEquals: { 1, 2, 3 }
Matchers.tests.cpp:<line number>: PASSED:
CHECK_THAT( v, UnorderedEquals<int>({ 3, 2, 1 }) )
with expansion:
{ 1, 2, 3 } UnorderedEquals: { 3, 2, 1 }
Matchers.tests.cpp:<line number>: PASSED: Matchers.tests.cpp:<line number>: PASSED:
CHECK_THAT( empty, UnorderedEquals(empty) ) CHECK_THAT( empty, UnorderedEquals(empty) )
with expansion: with expansion:
@@ -11271,6 +12015,16 @@ Matchers.tests.cpp:<line number>: PASSED:
with expansion: with expansion:
{ 2, 3, 1 } UnorderedEquals: { 1, 2, 3 } { 2, 3, 1 } UnorderedEquals: { 1, 2, 3 }
Matchers.tests.cpp:<line number>: PASSED:
CHECK_THAT( v5, (UnorderedEquals<int, std::allocator<int>, CustomAllocator<int>>(permuted)) )
with expansion:
{ 1, 2, 3 } UnorderedEquals: { 2, 3, 1 }
Matchers.tests.cpp:<line number>: PASSED:
CHECK_THAT( v5_permuted, UnorderedEquals(v5) )
with expansion:
{ 1, 3, 2 } UnorderedEquals: { 1, 2, 3 }
------------------------------------------------------------------------------- -------------------------------------------------------------------------------
Vector matchers that fail Vector matchers that fail
Contains (element) Contains (element)
@@ -13427,6 +14181,6 @@ Misc.tests.cpp:<line number>
Misc.tests.cpp:<line number>: PASSED: Misc.tests.cpp:<line number>: PASSED:
=============================================================================== ===============================================================================
test cases: 307 | 217 passed | 86 failed | 4 failed as expected test cases: 323 | 232 passed | 86 failed | 5 failed as expected
assertions: 1694 | 1525 passed | 148 failed | 21 failed as expected assertions: 1781 | 1608 passed | 148 failed | 25 failed as expected

View File

@@ -188,6 +188,569 @@ Compilation.tests.cpp:<line number>: PASSED:
with expansion: with expansion:
true true
-------------------------------------------------------------------------------
#1905 -- test spec parser properly clears internal state between compound tests
-------------------------------------------------------------------------------
CmdLine.tests.cpp:<line number>
...............................................................................
CmdLine.tests.cpp:<line number>: PASSED:
REQUIRE( spec.matches(fakeTestCase("spec . char")) )
with expansion:
true
CmdLine.tests.cpp:<line number>: PASSED:
REQUIRE( spec.matches(fakeTestCase("spec , char")) )
with expansion:
true
CmdLine.tests.cpp:<line number>: PASSED:
REQUIRE_FALSE( spec.matches(fakeTestCase(R"(spec \, char)")) )
with expansion:
!false
-------------------------------------------------------------------------------
#1912 -- test spec parser handles escaping
Various parentheses
-------------------------------------------------------------------------------
CmdLine.tests.cpp:<line number>
...............................................................................
CmdLine.tests.cpp:<line number>: PASSED:
REQUIRE( spec.matches(fakeTestCase(R"(spec {a} char)")) )
with expansion:
true
CmdLine.tests.cpp:<line number>: PASSED:
REQUIRE( spec.matches(fakeTestCase(R"(spec [a] char)")) )
with expansion:
true
CmdLine.tests.cpp:<line number>: PASSED:
REQUIRE_FALSE( spec.matches(fakeTestCase("differs but has similar tag", "[a]")) )
with expansion:
!false
-------------------------------------------------------------------------------
#1912 -- test spec parser handles escaping
backslash in test name
-------------------------------------------------------------------------------
CmdLine.tests.cpp:<line number>
...............................................................................
CmdLine.tests.cpp:<line number>: PASSED:
REQUIRE( spec.matches(fakeTestCase(R"(spec \ char)")) )
with expansion:
true
-------------------------------------------------------------------------------
#1913 - GENERATE inside a for loop should not keep recreating the generator
-------------------------------------------------------------------------------
Generators.tests.cpp:<line number>
...............................................................................
Generators.tests.cpp:<line number>: PASSED:
REQUIRE( counter < 7 )
with expansion:
3 < 7
-------------------------------------------------------------------------------
#1913 - GENERATE inside a for loop should not keep recreating the generator
-------------------------------------------------------------------------------
Generators.tests.cpp:<line number>
...............................................................................
Generators.tests.cpp:<line number>: PASSED:
REQUIRE( counter < 7 )
with expansion:
6 < 7
-------------------------------------------------------------------------------
#1913 - GENERATEs can share a line
-------------------------------------------------------------------------------
Generators.tests.cpp:<line number>
...............................................................................
Generators.tests.cpp:<line number>: PASSED:
REQUIRE( i != j )
with expansion:
1 != 3
-------------------------------------------------------------------------------
#1913 - GENERATEs can share a line
-------------------------------------------------------------------------------
Generators.tests.cpp:<line number>
...............................................................................
Generators.tests.cpp:<line number>: PASSED:
REQUIRE( i != j )
with expansion:
1 != 4
-------------------------------------------------------------------------------
#1913 - GENERATEs can share a line
-------------------------------------------------------------------------------
Generators.tests.cpp:<line number>
...............................................................................
Generators.tests.cpp:<line number>: PASSED:
REQUIRE( i != j )
with expansion:
2 != 3
-------------------------------------------------------------------------------
#1913 - GENERATEs can share a line
-------------------------------------------------------------------------------
Generators.tests.cpp:<line number>
...............................................................................
Generators.tests.cpp:<line number>: PASSED:
REQUIRE( i != j )
with expansion:
2 != 4
-------------------------------------------------------------------------------
#1938 - GENERATE after a section
A
-------------------------------------------------------------------------------
PartTracker.tests.cpp:<line number>
...............................................................................
PartTracker.tests.cpp:<line number>: PASSED:
with message:
A
-------------------------------------------------------------------------------
#1938 - GENERATE after a section
B
-------------------------------------------------------------------------------
PartTracker.tests.cpp:<line number>
...............................................................................
PartTracker.tests.cpp:<line number>: PASSED:
REQUIRE( m )
with expansion:
1
-------------------------------------------------------------------------------
#1938 - GENERATE after a section
B
-------------------------------------------------------------------------------
PartTracker.tests.cpp:<line number>
...............................................................................
PartTracker.tests.cpp:<line number>: PASSED:
REQUIRE( m )
with expansion:
2
-------------------------------------------------------------------------------
#1938 - GENERATE after a section
B
-------------------------------------------------------------------------------
PartTracker.tests.cpp:<line number>
...............................................................................
PartTracker.tests.cpp:<line number>: PASSED:
REQUIRE( m )
with expansion:
3
-------------------------------------------------------------------------------
#1938 - Section followed by flat generate
A
-------------------------------------------------------------------------------
PartTracker.tests.cpp:<line number>
...............................................................................
PartTracker.tests.cpp:<line number>: PASSED:
REQUIRE( 1 )
-------------------------------------------------------------------------------
#1938 - Section followed by flat generate
-------------------------------------------------------------------------------
PartTracker.tests.cpp:<line number>
...............................................................................
PartTracker.tests.cpp:<line number>: PASSED:
REQUIRE( m )
with expansion:
2
-------------------------------------------------------------------------------
#1938 - Section followed by flat generate
-------------------------------------------------------------------------------
PartTracker.tests.cpp:<line number>
...............................................................................
PartTracker.tests.cpp:<line number>: PASSED:
REQUIRE( m )
with expansion:
3
-------------------------------------------------------------------------------
#1938 - flat generate
-------------------------------------------------------------------------------
PartTracker.tests.cpp:<line number>
...............................................................................
PartTracker.tests.cpp:<line number>: PASSED:
REQUIRE( m )
with expansion:
1
-------------------------------------------------------------------------------
#1938 - flat generate
-------------------------------------------------------------------------------
PartTracker.tests.cpp:<line number>
...............................................................................
PartTracker.tests.cpp:<line number>: PASSED:
REQUIRE( m )
with expansion:
2
-------------------------------------------------------------------------------
#1938 - flat generate
-------------------------------------------------------------------------------
PartTracker.tests.cpp:<line number>
...............................................................................
PartTracker.tests.cpp:<line number>: PASSED:
REQUIRE( m )
with expansion:
3
-------------------------------------------------------------------------------
#1938 - mixed sections and generates
A
-------------------------------------------------------------------------------
PartTracker.tests.cpp:<line number>
...............................................................................
PartTracker.tests.cpp:<line number>: PASSED:
with message:
A
-------------------------------------------------------------------------------
#1938 - mixed sections and generates
-------------------------------------------------------------------------------
PartTracker.tests.cpp:<line number>
...............................................................................
PartTracker.tests.cpp:<line number>: PASSED:
with messages:
i := 1
j := 3
k := 5
-------------------------------------------------------------------------------
#1938 - mixed sections and generates
B
-------------------------------------------------------------------------------
PartTracker.tests.cpp:<line number>
...............................................................................
PartTracker.tests.cpp:<line number>: PASSED:
with message:
B
-------------------------------------------------------------------------------
#1938 - mixed sections and generates
-------------------------------------------------------------------------------
PartTracker.tests.cpp:<line number>
...............................................................................
PartTracker.tests.cpp:<line number>: PASSED:
with messages:
i := 1
j := 3
k := 6
-------------------------------------------------------------------------------
#1938 - mixed sections and generates
B
-------------------------------------------------------------------------------
PartTracker.tests.cpp:<line number>
...............................................................................
PartTracker.tests.cpp:<line number>: PASSED:
with message:
B
-------------------------------------------------------------------------------
#1938 - mixed sections and generates
-------------------------------------------------------------------------------
PartTracker.tests.cpp:<line number>
...............................................................................
PartTracker.tests.cpp:<line number>: PASSED:
with messages:
i := 1
j := 4
k := 5
-------------------------------------------------------------------------------
#1938 - mixed sections and generates
-------------------------------------------------------------------------------
PartTracker.tests.cpp:<line number>
...............................................................................
PartTracker.tests.cpp:<line number>: PASSED:
with messages:
i := 1
j := 4
k := 6
-------------------------------------------------------------------------------
#1938 - mixed sections and generates
A
-------------------------------------------------------------------------------
PartTracker.tests.cpp:<line number>
...............................................................................
PartTracker.tests.cpp:<line number>: PASSED:
with message:
A
-------------------------------------------------------------------------------
#1938 - mixed sections and generates
-------------------------------------------------------------------------------
PartTracker.tests.cpp:<line number>
...............................................................................
PartTracker.tests.cpp:<line number>: PASSED:
with messages:
i := 2
j := 3
k := 5
-------------------------------------------------------------------------------
#1938 - mixed sections and generates
B
-------------------------------------------------------------------------------
PartTracker.tests.cpp:<line number>
...............................................................................
PartTracker.tests.cpp:<line number>: PASSED:
with message:
B
-------------------------------------------------------------------------------
#1938 - mixed sections and generates
-------------------------------------------------------------------------------
PartTracker.tests.cpp:<line number>
...............................................................................
PartTracker.tests.cpp:<line number>: PASSED:
with messages:
i := 2
j := 3
k := 6
-------------------------------------------------------------------------------
#1938 - mixed sections and generates
B
-------------------------------------------------------------------------------
PartTracker.tests.cpp:<line number>
...............................................................................
PartTracker.tests.cpp:<line number>: PASSED:
with message:
B
-------------------------------------------------------------------------------
#1938 - mixed sections and generates
-------------------------------------------------------------------------------
PartTracker.tests.cpp:<line number>
...............................................................................
PartTracker.tests.cpp:<line number>: PASSED:
with messages:
i := 2
j := 4
k := 5
-------------------------------------------------------------------------------
#1938 - mixed sections and generates
-------------------------------------------------------------------------------
PartTracker.tests.cpp:<line number>
...............................................................................
PartTracker.tests.cpp:<line number>: PASSED:
with messages:
i := 2
j := 4
k := 6
-------------------------------------------------------------------------------
#1938 - nested generate
-------------------------------------------------------------------------------
PartTracker.tests.cpp:<line number>
...............................................................................
PartTracker.tests.cpp:<line number>: PASSED:
REQUIRE( m )
with expansion:
1
PartTracker.tests.cpp:<line number>: PASSED:
REQUIRE( n )
with expansion:
1
-------------------------------------------------------------------------------
#1938 - nested generate
-------------------------------------------------------------------------------
PartTracker.tests.cpp:<line number>
...............................................................................
PartTracker.tests.cpp:<line number>: PASSED:
REQUIRE( m )
with expansion:
1
PartTracker.tests.cpp:<line number>: PASSED:
REQUIRE( n )
with expansion:
2
-------------------------------------------------------------------------------
#1938 - nested generate
-------------------------------------------------------------------------------
PartTracker.tests.cpp:<line number>
...............................................................................
PartTracker.tests.cpp:<line number>: PASSED:
REQUIRE( m )
with expansion:
1
PartTracker.tests.cpp:<line number>: PASSED:
REQUIRE( n )
with expansion:
3
-------------------------------------------------------------------------------
#1938 - nested generate
-------------------------------------------------------------------------------
PartTracker.tests.cpp:<line number>
...............................................................................
PartTracker.tests.cpp:<line number>: PASSED:
REQUIRE( m )
with expansion:
2
PartTracker.tests.cpp:<line number>: PASSED:
REQUIRE( n )
with expansion:
1
-------------------------------------------------------------------------------
#1938 - nested generate
-------------------------------------------------------------------------------
PartTracker.tests.cpp:<line number>
...............................................................................
PartTracker.tests.cpp:<line number>: PASSED:
REQUIRE( m )
with expansion:
2
PartTracker.tests.cpp:<line number>: PASSED:
REQUIRE( n )
with expansion:
2
-------------------------------------------------------------------------------
#1938 - nested generate
-------------------------------------------------------------------------------
PartTracker.tests.cpp:<line number>
...............................................................................
PartTracker.tests.cpp:<line number>: PASSED:
REQUIRE( m )
with expansion:
2
PartTracker.tests.cpp:<line number>: PASSED:
REQUIRE( n )
with expansion:
3
-------------------------------------------------------------------------------
#1938 - nested generate
-------------------------------------------------------------------------------
PartTracker.tests.cpp:<line number>
...............................................................................
PartTracker.tests.cpp:<line number>: PASSED:
REQUIRE( m )
with expansion:
3
PartTracker.tests.cpp:<line number>: PASSED:
REQUIRE( n )
with expansion:
1
-------------------------------------------------------------------------------
#1938 - nested generate
-------------------------------------------------------------------------------
PartTracker.tests.cpp:<line number>
...............................................................................
PartTracker.tests.cpp:<line number>: PASSED:
REQUIRE( m )
with expansion:
3
PartTracker.tests.cpp:<line number>: PASSED:
REQUIRE( n )
with expansion:
2
-------------------------------------------------------------------------------
#1938 - nested generate
-------------------------------------------------------------------------------
PartTracker.tests.cpp:<line number>
...............................................................................
PartTracker.tests.cpp:<line number>: PASSED:
REQUIRE( m )
with expansion:
3
PartTracker.tests.cpp:<line number>: PASSED:
REQUIRE( n )
with expansion:
3
-------------------------------------------------------------------------------
#1954 - 7 arg template test case sig compiles - 1, 1, 1, 1, 1, 0, 0
-------------------------------------------------------------------------------
Misc.tests.cpp:<line number>
...............................................................................
Misc.tests.cpp:<line number>: PASSED:
-------------------------------------------------------------------------------
#1954 - 7 arg template test case sig compiles - 5, 1, 1, 1, 1, 0, 0
-------------------------------------------------------------------------------
Misc.tests.cpp:<line number>
...............................................................................
Misc.tests.cpp:<line number>: PASSED:
-------------------------------------------------------------------------------
#1954 - 7 arg template test case sig compiles - 5, 3, 1, 1, 1, 0, 0
-------------------------------------------------------------------------------
Misc.tests.cpp:<line number>
...............................................................................
Misc.tests.cpp:<line number>: PASSED:
------------------------------------------------------------------------------- -------------------------------------------------------------------------------
#748 - captures with unexpected exceptions #748 - captures with unexpected exceptions
outside assertions outside assertions
@@ -368,6 +931,6 @@ Condition.tests.cpp:<line number>: FAILED:
CHECK( true != true ) CHECK( true != true )
=============================================================================== ===============================================================================
test cases: 19 | 14 passed | 3 failed | 2 failed as expected test cases: 31 | 26 passed | 3 failed | 2 failed as expected
assertions: 42 | 35 passed | 4 failed | 3 failed as expected assertions: 100 | 93 passed | 4 failed | 3 failed as expected

File diff suppressed because it is too large Load Diff

View File

@@ -2,6 +2,9 @@
<testExecutions version="1"loose text artifact <testExecutions version="1"loose text artifact
> >
<file path="projects/<exe-name>/IntrospectiveTests/CmdLine.tests.cpp"> <file path="projects/<exe-name>/IntrospectiveTests/CmdLine.tests.cpp">
<testCase name="#1905 -- test spec parser properly clears internal state between compound tests" duration="{duration}"/>
<testCase name="#1912 -- test spec parser handles escaping/Various parentheses" duration="{duration}"/>
<testCase name="#1912 -- test spec parser handles escaping/backslash in test name" duration="{duration}"/>
<testCase name="Parse test names and tags/Empty test spec should have no filters" duration="{duration}"/> <testCase name="Parse test names and tags/Empty test spec should have no filters" duration="{duration}"/>
<testCase name="Parse test names and tags/Test spec from empty string should have no filters" duration="{duration}"/> <testCase name="Parse test names and tags/Test spec from empty string should have no filters" duration="{duration}"/>
<testCase name="Parse test names and tags/Test spec from just a comma should have no filters" duration="{duration}"/> <testCase name="Parse test names and tags/Test spec from just a comma should have no filters" duration="{duration}"/>
@@ -96,6 +99,15 @@
<testCase name="Generators internals/Range/Negative manual step/Integer/Slightly under end" duration="{duration}"/> <testCase name="Generators internals/Range/Negative manual step/Integer/Slightly under end" duration="{duration}"/>
</file> </file>
<file path="projects/<exe-name>/IntrospectiveTests/PartTracker.tests.cpp"> <file path="projects/<exe-name>/IntrospectiveTests/PartTracker.tests.cpp">
<testCase name="#1938 - GENERATE after a section/A" duration="{duration}"/>
<testCase name="#1938 - GENERATE after a section/B" duration="{duration}"/>
<testCase name="#1938 - Section followed by flat generate" duration="{duration}"/>
<testCase name="#1938 - Section followed by flat generate/A" duration="{duration}"/>
<testCase name="#1938 - flat generate" duration="{duration}"/>
<testCase name="#1938 - mixed sections and generates" duration="{duration}"/>
<testCase name="#1938 - mixed sections and generates/A" duration="{duration}"/>
<testCase name="#1938 - mixed sections and generates/B" duration="{duration}"/>
<testCase name="#1938 - nested generate" duration="{duration}"/>
<testCase name="Tracker" duration="{duration}"/> <testCase name="Tracker" duration="{duration}"/>
<testCase name="Tracker/successfully close one section" duration="{duration}"/> <testCase name="Tracker/successfully close one section" duration="{duration}"/>
<testCase name="Tracker/fail one section" duration="{duration}"/> <testCase name="Tracker/fail one section" duration="{duration}"/>
@@ -150,6 +162,7 @@
</file> </file>
<file path="projects/<exe-name>/IntrospectiveTests/ToString.tests.cpp"> <file path="projects/<exe-name>/IntrospectiveTests/ToString.tests.cpp">
<testCase name="Directly creating an EnumInfo" duration="{duration}"/> <testCase name="Directly creating an EnumInfo" duration="{duration}"/>
<testCase name="Range type with sentinel" duration="{duration}"/>
<testCase name="parseEnums/No enums" duration="{duration}"/> <testCase name="parseEnums/No enums" duration="{duration}"/>
<testCase name="parseEnums/One enum value" duration="{duration}"/> <testCase name="parseEnums/One enum value" duration="{duration}"/>
<testCase name="parseEnums/Multiple enum values" duration="{duration}"/> <testCase name="parseEnums/Multiple enum values" duration="{duration}"/>
@@ -369,6 +382,7 @@ Class.tests.cpp:<line number>
<testCase name="#809" duration="{duration}"/> <testCase name="#809" duration="{duration}"/>
<testCase name="#833" duration="{duration}"/> <testCase name="#833" duration="{duration}"/>
<testCase name="#872" duration="{duration}"/> <testCase name="#872" duration="{duration}"/>
<testCase name="Assertion macros support bit operators and bool conversions" duration="{duration}"/>
<testCase name="Lambdas in assertions" duration="{duration}"/> <testCase name="Lambdas in assertions" duration="{duration}"/>
<testCase name="Optionally static assertions" duration="{duration}"/> <testCase name="Optionally static assertions" duration="{duration}"/>
</file> </file>
@@ -561,6 +575,30 @@ Condition.tests.cpp:<line number>
</skipped> </skipped>
</testCase> </testCase>
<testCase name="Inequality checks that should succeed" duration="{duration}"/> <testCase name="Inequality checks that should succeed" duration="{duration}"/>
<testCase name="Mayfail test case with nested sections/1/A" duration="{duration}">
<skipped message="FAIL()">
FAILED:
Condition.tests.cpp:<line number>
</skipped>
</testCase>
<testCase name="Mayfail test case with nested sections/2/A" duration="{duration}">
<skipped message="FAIL()">
FAILED:
Condition.tests.cpp:<line number>
</skipped>
</testCase>
<testCase name="Mayfail test case with nested sections/1/B" duration="{duration}">
<skipped message="FAIL()">
FAILED:
Condition.tests.cpp:<line number>
</skipped>
</testCase>
<testCase name="Mayfail test case with nested sections/2/B" duration="{duration}">
<skipped message="FAIL()">
FAILED:
Condition.tests.cpp:<line number>
</skipped>
</testCase>
<testCase name="Ordering comparison checks that should fail" duration="{duration}"> <testCase name="Ordering comparison checks that should fail" duration="{duration}">
<failure message="CHECK(data.int_seven > 7)"> <failure message="CHECK(data.int_seven > 7)">
FAILED: FAILED:
@@ -871,6 +909,8 @@ Exception.tests.cpp:<line number>
</testCase> </testCase>
</file> </file>
<file path="projects/<exe-name>/UsageTests/Generators.tests.cpp"> <file path="projects/<exe-name>/UsageTests/Generators.tests.cpp">
<testCase name="#1913 - GENERATE inside a for loop should not keep recreating the generator" duration="{duration}"/>
<testCase name="#1913 - GENERATEs can share a line" duration="{duration}"/>
<testCase name="3x3x3 ints" duration="{duration}"/> <testCase name="3x3x3 ints" duration="{duration}"/>
<testCase name="Copy and then generate a range/from var and iterators" duration="{duration}"/> <testCase name="Copy and then generate a range/from var and iterators" duration="{duration}"/>
<testCase name="Copy and then generate a range/From a temporary container" duration="{duration}"/> <testCase name="Copy and then generate a range/From a temporary container" duration="{duration}"/>
@@ -896,6 +936,8 @@ Exception.tests.cpp:<line number>
<testCase name="Arbitrary predicate matcher/Function pointer" duration="{duration}"/> <testCase name="Arbitrary predicate matcher/Function pointer" duration="{duration}"/>
<testCase name="Arbitrary predicate matcher/Lambdas + different type" duration="{duration}"/> <testCase name="Arbitrary predicate matcher/Lambdas + different type" duration="{duration}"/>
<testCase name="Composed matchers are distinct" duration="{duration}"/> <testCase name="Composed matchers are distinct" duration="{duration}"/>
<testCase name="Composed matchers shortcircuit/&amp;&amp;" duration="{duration}"/>
<testCase name="Composed matchers shortcircuit/||" duration="{duration}"/>
<testCase name="Contains string matcher" duration="{duration}"> <testCase name="Contains string matcher" duration="{duration}">
<failure message="CHECK_THAT(testStringForMatching(), Contains(&quot;not there&quot;, Catch::CaseSensitive::No))"> <failure message="CHECK_THAT(testStringForMatching(), Contains(&quot;not there&quot;, Catch::CaseSensitive::No))">
FAILED: FAILED:
@@ -1346,6 +1388,9 @@ Message.tests.cpp:<line number>
<file path="projects/<exe-name>/UsageTests/Misc.tests.cpp"> <file path="projects/<exe-name>/UsageTests/Misc.tests.cpp">
<testCase name="# A test name that starts with a #" duration="{duration}"/> <testCase name="# A test name that starts with a #" duration="{duration}"/>
<testCase name="#1175 - Hidden Test" duration="{duration}"/> <testCase name="#1175 - Hidden Test" duration="{duration}"/>
<testCase name="#1954 - 7 arg template test case sig compiles - 1, 1, 1, 1, 1, 0, 0" duration="{duration}"/>
<testCase name="#1954 - 7 arg template test case sig compiles - 5, 1, 1, 1, 1, 0, 0" duration="{duration}"/>
<testCase name="#1954 - 7 arg template test case sig compiles - 5, 3, 1, 1, 1, 0, 0" duration="{duration}"/>
<testCase name="#835 -- errno should not be touched by Catch" duration="{duration}"> <testCase name="#835 -- errno should not be touched by Catch" duration="{duration}">
<skipped message="CHECK(f() == 0)"> <skipped message="CHECK(f() == 0)">
FAILED: FAILED:

Some files were not shown because too many files have changed in this diff Show More