Compare commits

..

71 Commits

Author SHA1 Message Date
Martin Hořeňovský
3f0283de7a v3.3.2 2023-02-27 15:12:49 +01:00
Martin Hořeňovský
6fbb3f0723 Add IsNaN matcher 2023-02-26 00:14:32 +01:00
Martin Hořeňovský
9ff3cde87b Simplify test name creation for list-templated test cases 2023-02-23 15:12:14 +01:00
Martin Hořeňovský
4d802ca58f Use StringRef UDL in more preprocessor-generated strings 2023-02-23 13:25:08 +01:00
Martin Hořeňovský
13711be7cf Use StringRef UDL for generated generator names 2023-02-23 13:25:07 +01:00
Martin Hořeňovský
27ba26f743 Merge pull request #2643 from kisielk/patch-1
cmake-integration.md: Use "tests" as test target name in all examples.
2023-02-22 20:59:12 +01:00
Martin Hořeňovský
a209bcfb54 Update build instructions in contributing.md
We now show the more modern `-S {source}` instead of the old and
undocumented `-H{source}` CMake flag, and also show the available
presets, instead of individually specifying the different testing
options.

Closes #2593
2023-02-22 20:11:45 +01:00
Martin Hořeňovský
584973a485 Early evaluate line loc in NameAndLoc::operator==
I do not know if checking the tracker name or the tracker's file
part of the location first would provide better results, but
in the common case, the line part of the location check should be
rather unique, because different `SECTION`s will have different
source lines where they are defined.

I also propagated this same check into `ITracker::findChild`,
because this significantly improves performance of section tracking
in Debug builds -> 10% in macro benchmark heavily focused on section
tracking. In Release build there is usually no difference, because
the inliner will inline `NameAndLoc::operator==` into `findChild`,
and then eliminate the redundant check. (If the inliner decides
against, then this still improves the performance on average).
2023-02-20 15:19:57 +01:00
Martin Hořeňovský
4f7c8cb28a Avoid copying NameAndLocationRef when passed as argument
`NameAndLocationRef` is pretty large type, so even in release build,
it is unlikely to be passed in registers. In addition to the fact
that some platforms currently do not allow passing even small types
in register (Windows ABI!!), it is better to pass it as a ref,
effectively passing around a pointer.
2023-02-20 15:17:35 +01:00
Martin Hořeňovský
e1dbad4c9e Inline StringRef::operator==
This enables its inlining even without LTO, which in turns enables
callers to determine that two StringRefs are unequals with simple
comparison of two numbers, without any function calls.
2023-02-20 15:05:09 +01:00
Martin Hořeňovský
2befd98da2 Inline some non-virtual functions in ITracker and TrackerContext 2023-02-20 15:02:50 +01:00
Martin Hořeňovský
00f259aeb2 Move captured output into TestCaseStats when sending testCaseEnded 2023-02-20 14:48:39 +01:00
Martin Hořeňovský
fed1436246 Avoid allocating trimmed name for SectionTracker 2023-02-20 14:32:46 +01:00
Martin Hořeňovský
0477326ad9 Directly construct empty string for invalid SectionInfo 2023-02-20 14:32:14 +01:00
Martin Hořeňovský
f04c93462b Small refactoring in AssertionResult 2023-02-20 14:32:12 +01:00
Martin Hořeňovský
1af351cea1 Remove unused TrackerContext::endRun function 2023-02-20 14:32:10 +01:00
Martin Hořeňovský
dcc9fa3f38 Use StringRef UDL for more string literals when expanding macros
* for the name of the listener when registering listener
* for the original expression in assertion macros
2023-02-20 14:31:26 +01:00
Martin Hořeňovský
bf6a15a69a Rewrite -# docs 2023-02-17 15:55:21 +01:00
Martin Hořeňovský
6135a78c31 Don't insert the foo part of [.foo] tag twice when parsing test spec 2023-02-13 22:16:53 +01:00
Martin Hořeňovský
e8ba329b6c Add support for iterator+sentinel pairs in Contains matcher 2023-02-10 23:25:45 +01:00
Martin Hořeňovský
4aa88299af Preconstruct error message in RunContext::handleIncomplete 2023-02-10 21:36:04 +01:00
Kamil Kisiel
4ff9be3bc5 cmake-integration.md: Use "tests" as test target name in all examples. 2023-02-10 11:09:26 -08:00
Martin Hořeňovský
76cdaa3b51 Merge pull request #2637 from jbadwaik/nvhpc_unused_warning
Suppress declared_but_not_referenced warning for NVHPC
2023-02-08 19:51:39 +01:00
Jayesh Badwaik (FZ Juelich)
644294df60 Suppress declared_but_not_referenced warning for NVHPC
Catch2 suppresses unused variable and equivalent warnings in a couple
  of places, but most importantly, in the declaration of autoRegistrar
  in test registry. This warning gets triggered by NVHPC compiler. The
  current patch adds three macros, namely:

      CATCH_INTERNAL_START_WARNINGS_SUPPRESSION
      CATCH_INTERNAL_SUPPRESS_UNUSED_VARIABLE_WARNINGS
      CATCH_INTERNAL_STOP_WARNINGS_SUPPRESSION

  for the NVHPC Compiler which in particular prevents that warning from
  occurring. The compiler is detected completely separately from the
  other compilers in this patch, because from what I found out, NVHPC
  defines __GNUC__ as well for some reason. (I suspect because it
  advertises itself as GNU compatible.)

  We also add a condition to make sure that the `__GNUC__` path is not
  taken by the NVHPC compiler.
2023-02-08 12:40:55 +01:00
Martin Hořeňovský
cefa8fcf32 Enable use of UnorderedRangeEquals with iterator+sentinel pairs 2023-02-06 15:34:38 +01:00
Martin Hořeňovský
772fa3f790 Add Catch::Detail::is_permutation that supports sentinels
Also split out helpers for testing matcher ranges (types whose
begin/end/empty/etc require ADL lookup, types whose iteration
uses iterator + sentinel pair, etc) into their own file.
2023-02-06 15:29:01 +01:00
Martin Hořeňovský
f3c0a3cd09 Fix RangeEquals matcher to handle iterator + sentinel ranges
Also added tests for types that require ADL lookup for their
`begin` and `end`.
2023-02-03 18:22:41 +01:00
Martin Hořeňovský
42d9d4533e Add test for empty result of filter generator 2023-02-01 18:27:41 +01:00
Martin Hořeňovský
618d44c448 Update docs about thread safe assertions 2023-02-01 15:24:47 +01:00
Martin Hořeňovský
388f7e1737 Cleanup unneeded allocations from reporters
The CompactReporter changes save 21 (430764 -> 430743) allocations
when running the SelfTest binary in default configuration. They
save about 500 allocations when running the binary with `-s`.
2023-01-30 15:30:36 +01:00
Martin Hořeňovský
2ab20a0e00 v3.3.1 2023-01-29 23:18:57 +01:00
Martin Hořeňovský
60264b8807 Avoid copying strings in sonarqube when sorting tests by file 2023-01-29 20:45:13 +01:00
Martin Hořeňovský
65ffee5189 Don't take ownership of SECTION's name for inactive sections
This eliminates 1945 (432709 -> 430764) allocations from running
`./tests/SelfTest -o /dev/null`. In general terms, this saves
an allocation every time an unvisited `SECTION` is passed, which
means that the saved allocations are quadratic in number of sibling
(same level) `SECTION`s in a test case.
2023-01-29 10:44:20 +01:00
Martin Hořeňovský
43f02027e4 Avoid allocations when looking for trackers
Now we delay allocating owning `NameAndLocation` instances until
we construct a new tracker (because a tracker's lifetime can be
significantly different from the underlying tracked-thing's name).

This saves 4239 allocations (436948 -> 432709) when running
`./tests/SelfTest -o /dev/null`, at some cost to code clarity
due to introducing a new ref type, `NameAndLocationRef`.
2023-01-29 10:14:20 +01:00
Martin Hořeňovský
906552f8c8 Clean up extraneous copies in Messages
This removes 109 allocations from running `tests/SelfTest`
(437057 -> 436948).
2023-01-28 22:14:37 +01:00
Martin Hořeňovský
356dfc1439 Move name and sample analysis in benchmarks into BenchmarkStats
This always saves 1 allocation per benchmark, and another two
allocations if the benchmark name is longer than the SSO buffer.
2023-01-28 21:40:59 +01:00
Martin Hořeňovský
e5d1eb757f Move AssertionResultData into AssertionResult in RunContext
When running `./tests/SelfTest -o /dev/null`, this saves 109
allocations (437167 -> 437058).
2023-01-28 19:57:38 +01:00
Martin Hořeňovský
2403f5620e Move SectionEndInfo into sectionEnded call in SECTION's destructor
When running `./tests/SelfTest -o /dev/null`, this saves 1272
allocations (437439 -> 437167). In general, this saves multiple
allocations per end of an entered `SECTION`, if the section name
was too long for SSO, because `RunContext::sectionEnded` can then
move the section's name further down the callstack.
2023-01-28 13:00:30 +01:00
Martin Hořeňovský
d58491c85a Move sectionInfo into sectionEndInfo when SECTION ends
When running `./tests/SelfTest -o /dev/null`, this saves 468
allocations (438907 -> 437439). In general, this saves 1 allocation
every time an entered `SECTION` ends and the section name was long
enough to move out of the SSO buffer.
2023-01-28 12:56:29 +01:00
Martin Hořeňovský
c837cb4a8a v3.3.0 2023-01-22 19:53:12 +01:00
Martin Hořeňovský
8359a6b244 Stop exceptions in generator constructors from aborting the binary
Fixes #2615
2023-01-22 16:04:16 +01:00
Martin Hořeňovský
adf43494e1 Add missing version information to matchers.md 2023-01-22 00:35:32 +01:00
John Beard
efca9a0f18 Added ElementsAre and UnorderedElementsAre (#2377)
Co-authored-by: Garz4 <fancygarz4@gmail.com>
Co-authored-by: Martin Hořeňovský <martin.horenovsky@gmail.com>
2023-01-22 00:33:04 +01:00
Martin Hořeňovský
dd36f83b88 Merge pull request #2630 from ChrisThrasher/export_all_symbols
Export symbols for all compilers on Windows
2023-01-21 15:14:24 +01:00
Chris Thrasher
baab9e8d28 Export symbols for all compilers on Windows 2023-01-20 16:16:30 -07:00
Martin Hořeňovský
2d3c9713a3 Remove VS2015 workaround from Detail::generate 2023-01-19 10:34:57 +01:00
Arash Badie-Modiri
956f915e31 Document template macros are in spearate header
Type parametrised and signature parametrised test macros are now in their own header. The documentation should reflect that.
2023-01-18 23:16:55 +01:00
Tommy Carozzani
aa8da505ec Fix compatibility with previous CUDA versions 2023-01-18 11:57:00 +01:00
Martin Hořeňovský
e27bb7198d Fix macro-redefinition issue with MSVC+CUDA
Closes #2603
2023-01-18 11:57:00 +01:00
Martin Hořeňovský
3486f8ed9e Update generator docs 2023-01-18 11:55:53 +01:00
Sergey Fedorov
b5be642042 catch_debugger.hpp: restore PPC support (#2619) 2023-01-14 00:03:30 +01:00
Martin Hořeňovský
d59572f46f Reword the SKIP docs a bit 2023-01-12 20:39:03 +01:00
Martin Hořeňovský
16f48f8c7c Add SUCCEED and FAIL docs next to SKIP docs 2023-01-12 20:38:58 +01:00
Martin Hořeňovský
367c2cb248 Update doc about what counts as unique test case 2023-01-12 15:26:32 +01:00
Philip Salzmann
d548be26e3 Add new SKIP macro for skipping tests at runtime (#2360)
* Add new SKIP macro for skipping tests at runtime

This adds a new `SKIP` macro for dynamically skipping tests at runtime.
The "skipped" status of a test case is treated as a first-class citizen,
like "succeeded" or "failed", and is reported with a new color on the
console.

* Don't show "skipped assertions" in console/compact reporters

Also extend skip tests to cover a few more use cases.

* Return exit code 4 if all test cases are skipped

* Use LightGrey for the skip colour

This isn't great, but is better than the deep blue that was borderline
invisible on dark backgrounds. The fix is to redo the colouring
a bit, including introducing light-blue that is actually visible.

* Add support for explicit skips in all reporters

* --allow-running-no-tests also allows all tests to be skipped

* Add docs for SKIP macro, deprecate IEventListener::skipTest

Co-authored-by: Martin Hořeňovský <martin.horenovsky@gmail.com>
2023-01-12 15:01:47 +01:00
Sam James
52066dbc2a Fix build with GCC 13 (add missing <cstdint> include)
GCC 13 (as usual for new compiler releases) shuffles around some
internal includes and so <cstdint> is no longer transitively included.

Explicitly include <cstdint> for uint64_t.

```
FAILED: src/CMakeFiles/Catch2.dir/catch2/internal/catch_clara.cpp.o
/usr/lib/ccache/bin/g++-13  -I/var/tmp/portage/dev-cpp/catch-3.0.1/work/Catch2-3.0.1/src/catch2/.. -I/var/tmp/portage/dev-cpp/catch-3.0.1/work/Catch2-3.0.1_build/generated-includes  -O2 -pipe
-march=native -fdiagnostics-color=always -frecord-gcc-switches -Wreturn-type -D_GLIBCXX_ASSERTIONS  -ggdb3 -fdiagnostics-color=always
-ffile-prefix-map=/var/tmp/portage/dev-cpp/catch-3.0.1/work/Catch2-3.0.1=. -Wall -Wc++20-compat -Wcast-align -Wcatch-value -Wdeprecated -Wexceptions -Wextra -Wextra-semi -Wfloat-equal -Winit-self
-Wmisleading-indentation -Wmismatched-new-delete -Wmismatched-tags -Wmissing-braces -Wmissing-declarations -Wmissing-noreturn -Wnull-dereference -Wold-style-cast -Woverloaded-virtual -Wparentheses
-Wpedantic -Wreorder -Wshadow -Wstrict-aliasing -Wsuggest-override -Wundef -Wuninitialized -Wunreachable-code -Wunused -Wunused-function -Wunused-parameter -Wvla -MD -MT
src/CMakeFiles/Catch2.dir/catch2/internal/catch_clara.cpp.o -MF src/CMakeFiles/Catch2.dir/catch2/internal/catch_clara.cpp.o.d -o src/CMakeFiles/Catch2.dir/catch2/internal/catch_clara.cpp.o -c
/var/tmp/portage/dev-cpp/catch-3.0.1/work/Catch2-3.0.1/src/catch2/internal/catch_clara.cpp
In file included from /var/tmp/portage/dev-cpp/catch-3.0.1/work/Catch2-3.0.1/src/catch2/internal/catch_clara.cpp:12:
/var/tmp/portage/dev-cpp/catch-3.0.1/work/Catch2-3.0.1/src/catch2/../catch2/internal/catch_string_manip.hpp:47:14: error: 'uint64_t' in namespace 'std' does not name a type; did you mean 'wint_t'?
   47 |         std::uint64_t m_count;
      |              ^~~~~~~~
      |              wint_t
/var/tmp/portage/dev-cpp/catch-3.0.1/work/Catch2-3.0.1/src/catch2/../catch2/internal/catch_string_manip.hpp:51:42: error: expected ')' before 'count'
   51 |         constexpr pluralise(std::uint64_t count, StringRef label):
      |                            ~             ^~~~~~
      |                                          )
```
2023-01-08 20:08:58 +01:00
TrueWodzu
cdf604f30e Update command-line.md
Typo in "--list-reporter" link, should be "--list-reporters"
2023-01-08 19:37:16 +01:00
Martin Hořeňovský
04382af4c6 Slightly better clang-format
Notably clang-format will no longer try to place template header
onto the same line as the function declaration.

Sadly it will still do it for attributes, because it took until
clang-format 16 for it to get the relevant option.
2023-01-05 23:02:51 +01:00
Martin Hořeňovský
ac93f19437 Improved path normalization in approvalTests.py
Instead of redoing the whole line where path was found, only the
directory part of the path is removed, instead of removing all
of the line before the path starts.

This results in slight change in how junit and sonarqube approvals
come out, and significant change in how TeamCity reporter approvals
come out. This latter difference is the reason for the change,
as now the lines with `testFailed` and `testIgnored` messages
are not completely butchered.
2023-01-01 20:27:59 +01:00
Martin Hořeňovský
72b60dfd28 Cleanup the Windows GHA builds
* Use CMD as the shell and simplify configure/build steps
* Include plaform in the build name
2022-12-30 23:58:05 +01:00
Martin Hořeňovský
0c62167fea Merge pull request #2604 from ChrisThrasher/generated_includes_directory
Keep generated headers within project binary directory
2022-12-28 21:19:53 +01:00
Chris Thrasher
1be954ff70 Keep generated headers within project binary directory
This stops them from appearing in the build directories of projects
that may consume Catch2.
2022-12-26 22:44:35 -06:00
Martin Hořeňovský
78bb4fda05 Mention that the benchmarks are not run by default next to example 2022-12-18 21:42:40 +01:00
Martin Hořeňovský
e6ec1c238b Fix benchmarking example in the main readme
This uses the same fibonacci implementation as is used in the
benchmark test.

Closes #2568
2022-12-18 21:33:45 +01:00
mrbald
477c1f5152 Fixed typo in code example in top level README.md 2022-12-17 21:34:37 +01:00
Martin Hořeňovský
f8b9f77259 Prune Appveyor builds 2022-12-16 22:37:33 +01:00
Martin Hořeňovský
77fbacb03f Add VS 2019-2022 C+14/17 jobs to GHA
For now I added only the basic build matrix, without coverage
collection and more special builds, like WMAIN.

However, due to GHA being so much faster than AppVeyor, all
these builds are now done against the 'all-tests' prefix, making
the builds more uniform than they were on AppVeyor.
2022-12-16 22:34:33 +01:00
lbckmnn
e3fc97dffb fix compiler warning in parseUint and catch only relevant exceptions (#2572) 2022-12-12 12:15:42 +01:00
lbckmnn
9c0533a905 Add MessageMatches matcher for exception (#2570) 2022-12-12 00:40:47 +01:00
Martin Hořeňovský
ed02710b83 Make AutoReg in test registration macros const 2022-12-10 21:37:21 +01:00
Sergio Arroutbi
8b84438be4 Avoid usage of master when possible
Signed-off-by: Sergio Arroutbi <sarroutb@redhat.com>
2022-12-09 23:22:10 +01:00
116 changed files with 10247 additions and 4090 deletions

View File

@@ -4,41 +4,42 @@ Standard: c++14
# Note that we cannot use IncludeIsMainRegex functionality, because it # Note that we cannot use IncludeIsMainRegex functionality, because it
# does not support includes in angle brackets (<>) # does not support includes in angle brackets (<>)
SortIncludes: True SortIncludes: true
IncludeBlocks: Regroup IncludeBlocks: Regroup
IncludeCategories: IncludeCategories:
- Regex: '<catch2/.*\.hpp>' - Regex: <catch2/.*\.hpp>
Priority: 1 Priority: 1
- Regex: '<.*/.*\.hpp>' - Regex: <.*/.*\.hpp>
Priority: 2 Priority: 2
- Regex: '<.*>' - Regex: <.*>
Priority: 3 Priority: 3
AllowShortBlocksOnASingleLine: Always AllowShortBlocksOnASingleLine: Always
AllowShortEnumsOnASingleLine: false AllowShortEnumsOnASingleLine: false
AllowShortFunctionsOnASingleLine: All AllowShortFunctionsOnASingleLine: All
AllowShortIfStatementsOnASingleLine: WithoutElse AllowShortIfStatementsOnASingleLine: WithoutElse
AllowShortLambdasOnASingleLine: Inline AllowShortLambdasOnASingleLine: Inline
AccessModifierOffset: '-4' AccessModifierOffset: "-4"
AlignEscapedNewlines: Left AlignEscapedNewlines: Left
AllowAllConstructorInitializersOnNextLine: 'true' AllowAllConstructorInitializersOnNextLine: "true"
BinPackArguments: 'false' BinPackArguments: "false"
BinPackParameters: 'false' BinPackParameters: "false"
BreakConstructorInitializers: AfterColon BreakConstructorInitializers: AfterColon
ConstructorInitializerAllOnOneLineOrOnePerLine: 'true' ConstructorInitializerAllOnOneLineOrOnePerLine: "true"
DerivePointerAlignment: 'false' DerivePointerAlignment: "false"
FixNamespaceComments: 'true' FixNamespaceComments: "true"
IndentCaseLabels: 'false' IndentCaseLabels: "false"
IndentPPDirectives: AfterHash IndentPPDirectives: AfterHash
IndentWidth: '4' IndentWidth: "4"
NamespaceIndentation: All NamespaceIndentation: All
PointerAlignment: Left PointerAlignment: Left
SpaceBeforeCtorInitializerColon: 'false' SpaceBeforeCtorInitializerColon: "false"
SpaceInEmptyParentheses: 'false' SpaceInEmptyParentheses: "false"
SpacesInParentheses: 'true' SpacesInParentheses: "true"
TabWidth: '4' TabWidth: "4"
UseTab: Never UseTab: Never
AlwaysBreakTemplateDeclarations: Yes
... SpaceAfterTemplateKeyword: true
SortUsingDeclarations: true
ReflowComments: true

View File

@@ -0,0 +1,37 @@
name: Windows builds (basic)
on: [push, pull_request]
jobs:
build:
name: ${{matrix.os}}, ${{matrix.std}}, ${{matrix.build_type}}, ${{matrix.platform}}
runs-on: ${{matrix.os}}
strategy:
matrix:
os: [windows-2019, windows-2022]
platform: [Win32, x64]
build_type: [Debug, Release]
std: [14, 17]
steps:
- uses: actions/checkout@v2
- name: Configure build
working-directory: ${{runner.workspace}}
run: |
cmake -S $Env:GITHUB_WORKSPACE `
-B ${{runner.workspace}}/build `
-DCMAKE_CXX_STANDARD=${{matrix.std}} `
-A ${{matrix.platform}} `
--preset all-tests
- name: Build tests
working-directory: ${{runner.workspace}}
run: cmake --build build --config ${{matrix.build_type}} --parallel %NUMBER_OF_PROCESSORS%
shell: cmd
- name: Run tests
working-directory: ${{runner.workspace}}/build
env:
CTEST_OUTPUT_ON_FAILURE: 1
run: ctest -C ${{matrix.build_type}} -j %NUMBER_OF_PROCESSORS%
shell: cmd

View File

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

View File

@@ -1319,7 +1319,7 @@ CHM_FILE =
HHC_LOCATION = HHC_LOCATION =
# The GENERATE_CHI flag controls if a separate .chi index file is generated # The GENERATE_CHI flag controls if a separate .chi index file is generated
# (YES) or that it should be included in the master .chm file (NO). # (YES) or that it should be included in the main .chm file (NO).
# The default value is: NO. # The default value is: NO.
# This tag requires that the tag GENERATE_HTMLHELP is set to YES. # This tag requires that the tag GENERATE_HTMLHELP is set to YES.

View File

@@ -47,24 +47,28 @@ TEST_CASE( "Factorials are computed", "[factorial]" ) {
#include <cstdint> #include <cstdint>
uint64_t fibonacci(uint64_t number) { uint64_t fibonacci(uint64_t number) {
return number < 2 ? 1 : fibonacci(number - 1) + fibonacci(number - 2); return number < 2 ? number : fibonacci(number - 1) + fibonacci(number - 2);
} }
TEST_CASE("Benchmark Fibonacci", "[!benchmark]") { TEST_CASE("Benchmark Fibonacci", "[!benchmark]") {
REQUIRE(Fibonacci(5) == 5); REQUIRE(fibonacci(5) == 5);
REQUIRE(Fibonacci(20) == 6'765); REQUIRE(fibonacci(20) == 6'765);
BENCHMARK("Fibonacci 20") { BENCHMARK("fibonacci 20") {
return Fibonacci(20); return fibonacci(20);
}; };
REQUIRE(Fibonacci(25) == 75'025); REQUIRE(fibonacci(25) == 75'025);
BENCHMARK("Fibonacci 25") { BENCHMARK("fibonacci 25") {
return Fibonacci(25); return fibonacci(25);
}; };
} }
``` ```
_Note that benchmarks are not run by default, so you need to run it explicitly
with the `[!benchmark]` tag._
## Catch2 v3 has been released! ## Catch2 v3 has been released!
You are on the `devel` branch, where the v3 version is being developed. You are on the `devel` branch, where the v3 version is being developed.

View File

@@ -51,18 +51,6 @@ test_script:
# build explicitly. # build explicitly.
environment: environment:
matrix: matrix:
- FLAVOR: VS 2019 x64 Debug Surrogates Configure Tests
APPVEYOR_BUILD_WORKER_IMAGE: Visual Studio 2019
surrogates: 1
configure_tests: 1
platform: x64
configuration: Debug
- FLAVOR: VS 2019 x64 Release
APPVEYOR_BUILD_WORKER_IMAGE: Visual Studio 2019
platform: x64
configuration: Release
- FLAVOR: VS 2019 x64 Debug Coverage Examples - FLAVOR: VS 2019 x64 Debug Coverage Examples
APPVEYOR_BUILD_WORKER_IMAGE: Visual Studio 2019 APPVEYOR_BUILD_WORKER_IMAGE: Visual Studio 2019
examples: 1 examples: 1
@@ -77,11 +65,6 @@ environment:
platform: x64 platform: x64
configuration: Debug configuration: Debug
- FLAVOR: VS 2019 Win32 Debug
APPVEYOR_BUILD_WORKER_IMAGE: Visual Studio 2019
platform: Win32
configuration: Debug
- FLAVOR: VS 2019 x64 Debug Latest Strict - FLAVOR: VS 2019 x64 Debug Latest Strict
APPVEYOR_BUILD_WORKER_IMAGE: Visual Studio 2019 APPVEYOR_BUILD_WORKER_IMAGE: Visual Studio 2019
additional_flags: "/permissive- /std:c++latest" additional_flags: "/permissive- /std:c++latest"
@@ -93,37 +76,8 @@ environment:
platform: x64 platform: x64
configuration: Debug configuration: Debug
- FLAVOR: VS 2017 x64 Release
APPVEYOR_BUILD_WORKER_IMAGE: Visual Studio 2017
platform: x64
configuration: Release
- FLAVOR: VS 2017 x64 Release Coverage - FLAVOR: VS 2017 x64 Release Coverage
APPVEYOR_BUILD_WORKER_IMAGE: Visual Studio 2017 APPVEYOR_BUILD_WORKER_IMAGE: Visual Studio 2017
coverage: 1 coverage: 1
platform: x64 platform: x64
configuration: Debug configuration: Debug
- FLAVOR: VS 2017 Win32 Debug
APPVEYOR_BUILD_WORKER_IMAGE: Visual Studio 2017
platform: Win32
configuration: Debug
- FLAVOR: VS 2017 Win32 Debug Examples
APPVEYOR_BUILD_WORKER_IMAGE: Visual Studio 2017
examples: 1
platform: Win32
configuration: Debug
- FLAVOR: VS 2017 Win32 Debug WMain
APPVEYOR_BUILD_WORKER_IMAGE: Visual Studio 2017
wmain: 1
additional_flags: "/D_UNICODE /DUNICODE"
platform: Win32
configuration: Debug
- FLAVOR: VS 2017 x64 Debug Latest Strict
APPVEYOR_BUILD_WORKER_IMAGE: Visual Studio 2017
additional_flags: "/permissive- /std:c++latest"
platform: x64
configuration: Debug

View File

@@ -11,6 +11,7 @@ Once you're up and running consider the following reference material.
* [Logging macros](logging.md#top) * [Logging macros](logging.md#top)
* [Test cases and sections](test-cases-and-sections.md#top) * [Test cases and sections](test-cases-and-sections.md#top)
* [Test fixtures](test-fixtures.md#top) * [Test fixtures](test-fixtures.md#top)
* [Explicitly skipping, passing, and failing tests at runtime](skipping-passing-failing.md#top)
* [Reporters (output customization)](reporters.md#top) * [Reporters (output customization)](reporters.md#top)
* [Event Listeners](event-listeners.md#top) * [Event Listeners](event-listeners.md#top)
* [Data Generators (value parameterized tests)](generators.md#top) * [Data Generators (value parameterized tests)](generators.md#top)

View File

@@ -90,12 +90,12 @@ cmake_minimum_required(VERSION 3.5)
project(baz LANGUAGES CXX VERSION 0.0.1) project(baz LANGUAGES CXX VERSION 0.0.1)
find_package(Catch2 REQUIRED) find_package(Catch2 REQUIRED)
add_executable(foo test.cpp) add_executable(tests test.cpp)
target_link_libraries(foo PRIVATE Catch2::Catch2) target_link_libraries(tests PRIVATE Catch2::Catch2)
include(CTest) include(CTest)
include(Catch) include(Catch)
catch_discover_tests(foo) catch_discover_tests(tests)
``` ```
When using `FetchContent`, `include(Catch)` will fail unless When using `FetchContent`, `include(Catch)` will fail unless
@@ -108,7 +108,7 @@ directory.
list(APPEND CMAKE_MODULE_PATH ${catch2_SOURCE_DIR}/extras) list(APPEND CMAKE_MODULE_PATH ${catch2_SOURCE_DIR}/extras)
include(CTest) include(CTest)
include(Catch) include(Catch)
catch_discover_tests() catch_discover_tests(tests)
``` ```
#### Customization #### Customization
@@ -222,12 +222,12 @@ cmake_minimum_required(VERSION 3.5)
project(baz LANGUAGES CXX VERSION 0.0.1) project(baz LANGUAGES CXX VERSION 0.0.1)
find_package(Catch2 REQUIRED) find_package(Catch2 REQUIRED)
add_executable(foo test.cpp) add_executable(tests test.cpp)
target_link_libraries(foo PRIVATE Catch2::Catch2) target_link_libraries(tests PRIVATE Catch2::Catch2)
include(CTest) include(CTest)
include(ParseAndAddCatchTests) include(ParseAndAddCatchTests)
ParseAndAddCatchTests(foo) ParseAndAddCatchTests(tests)
``` ```

View File

@@ -148,7 +148,7 @@ validity, and throw an error if they are wrong._
> Support for passing arguments to reporters through the `-r`, `--reporter` flag was introduced in Catch2 3.0.1 > Support for passing arguments to reporters through the `-r`, `--reporter` flag was introduced in Catch2 3.0.1
There are multiple built-in reporters, you can see what they do by using the There are multiple built-in reporters, you can see what they do by using the
[`--list-reporter`](command-line.md#listing-available-tests-tags-or-reporters) [`--list-reporters`](command-line.md#listing-available-tests-tags-or-reporters)
flag. If you need a reporter providing custom format outside of the already flag. If you need a reporter providing custom format outside of the already
provided ones, look at the ["write your own reporter" part of the reporter provided ones, look at the ["write your own reporter" part of the reporter
documentation](reporters.md#writing-your-own-reporter). documentation](reporters.md#writing-your-own-reporter).
@@ -507,10 +507,13 @@ start of the first section.</br>
## Filenames as tags ## Filenames as tags
<pre>-#, --filenames-as-tags</pre> <pre>-#, --filenames-as-tags</pre>
When this option is used then every test is given an additional tag which is formed of the unqualified This option adds an extra tag to all test cases. The tag is `#` followed
filename it is found in, with any extension stripped, prefixed with the `#` character. by the unqualified filename the test case is defined in, with the _last_
extension stripped out.
For example, tests within the file `tests\SelfTest\UsageTests\BDD.tests.cpp`
will be given the `[#BDD.tests]` tag.
So, for example, tests within the file `~\Dev\MyProject\Ferrets.cpp` would be tagged `[#Ferrets]`.
<a id="colour-mode"></a> <a id="colour-mode"></a>
## Override output colouring ## Override output colouring
@@ -561,10 +564,10 @@ processes, as is done with the [Bazel test sharding](https://docs.bazel.build/ve
> Introduced in Catch2 3.0.1. > Introduced in Catch2 3.0.1.
By default, Catch2 test binaries return non-0 exit code if no tests were By default, Catch2 test binaries return non-0 exit code if no tests were run,
run, e.g. if the binary was compiled with no tests, or the provided test e.g. if the binary was compiled with no tests, the provided test spec matched no
spec matched no tests. This flag overrides that, so a test run with no tests, or all tests [were skipped at runtime](skipping-passing-failing.md#top). This flag
tests still returns 0. overrides that, so a test run with no tests still returns 0.
## Output verbosity ## Output verbosity
``` ```

View File

@@ -55,6 +55,15 @@ tests from `SelfTest` through a specific reporter and then compare the
generated output with a known good output ("Baseline"). By default, new generated output with a known good output ("Baseline"). By default, new
tests should be placed here. tests should be placed here.
To configure a Catch2 build with just the basic tests, use the `basic-tests`
preset, like so:
```
# Assuming you are in Catch2's root folder
cmake -B basic-test-build -S . -DCMAKE_BUILD_TYPE=Debug --preset basic-tests
```
However, not all tests can be written as plain unit tests. For example, 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 checking that Catch2 orders tests randomly when asked to, and that this
random ordering is subset-invariant, is better done as an integration random ordering is subset-invariant, is better done as an integration
@@ -76,21 +85,23 @@ configuration and require separate compilation.
Finally, CMake config tests test that you set Catch2's compile-time Finally, CMake config tests test that you set Catch2's compile-time
configuration options through CMake, using CMake options of the same name. configuration options through CMake, using CMake options of the same name.
None of these tests are enabled by default. To enable them, add These test categories can be enabled one by one, by passing
`-DCATCH_BUILD_EXAMPLES=ON`, `-DCATCH_BUILD_EXTRA_TESTS=ON`, and `-DCATCH_BUILD_EXAMPLES=ON`, `-DCATCH_BUILD_EXTRA_TESTS=ON`, and
`-DCATCH_ENABLE_CONFIGURE_TESTS=ON` when configuration the CMake build. `-DCATCH_ENABLE_CONFIGURE_TESTS=ON` when configuring the build.
Bringing this all together, the steps below should configure, build, Catch2 also provides a preset that promises to enable _all_ test types,
and run all tests in the `Debug` compilation. `all-tests`.
The snippet below will build & run all tests, in `Debug` compilation mode.
<!-- snippet: catch2-build-and-test --> <!-- snippet: catch2-build-and-test -->
<a id='snippet-catch2-build-and-test'></a> <a id='snippet-catch2-build-and-test'></a>
```sh ```sh
# 1. Regenerate the amalgamated distribution # 1. Regenerate the amalgamated distribution (some tests are built against it)
./tools/scripts/generateAmalgamatedFiles.py ./tools/scripts/generateAmalgamatedFiles.py
# 2. Configure the full test build # 2. Configure the full test build
cmake -Bdebug-build -H. -DCMAKE_BUILD_TYPE=Debug -DCATCH_DEVELOPMENT_BUILD=ON -DCATCH_BUILD_EXAMPLES=ON -DCATCH_BUILD_EXTRA_TESTS=ON cmake -B debug-build -S . -DCMAKE_BUILD_TYPE=Debug --preset all-tests
# 3. Run the actual build # 3. Run the actual build
cmake --build debug-build cmake --build debug-build

View File

@@ -26,6 +26,15 @@ to accurately probe the environment for this information so the flag
where it will export `BAZEL_TEST=1` for purposes like the above. Catch2 where it will export `BAZEL_TEST=1` for purposes like the above. Catch2
will now instead inspect the environment instead of relying on build configuration. will now instead inspect the environment instead of relying on build configuration.
### `IEventLister::skipTest( TestCaseInfo const& testInfo )`
This event (including implementations in derived classes such as `ReporterBase`)
is deprecated and will be removed in the next major release. It is currently
invoked for all test cases that are not going to be executed due to the test run
being aborted (when using `--abort` or `--abortx`). It is however
**NOT** invoked for test cases that are [explicitly skipped using the `SKIP`
macro](skipping-passing-failing.md#top).
--- ---
[Home](Readme.md#top) [Home](Readme.md#top)

View File

@@ -205,13 +205,17 @@ struct IGenerator : GeneratorUntypedBase {
// Precondition: // Precondition:
// The generator is either freshly constructed or the last call to next() returned true // The generator is either freshly constructed or the last call to next() returned true
virtual T const& get() const = 0; virtual T const& get() const = 0;
// Returns user-friendly string showing the current generator element
// Does not have to be overridden, IGenerator provides default implementation
virtual std::string stringifyImpl() const;
}; };
``` ```
However, to be able to use your custom generator inside `GENERATE`, it However, to be able to use your custom generator inside `GENERATE`, it
will need to be wrapped inside a `GeneratorWrapper<T>`. will need to be wrapped inside a `GeneratorWrapper<T>`.
`GeneratorWrapper<T>` is a value wrapper around a `GeneratorWrapper<T>` is a value wrapper around a
`std::unique_ptr<IGenerator<T>>`. `Catch::Detail::unique_ptr<IGenerator<T>>`.
For full example of implementing your own generator, look into Catch2's For full example of implementing your own generator, look into Catch2's
examples, specifically examples, specifically

View File

@@ -88,8 +88,8 @@ because only one thread passes the `REQUIRE` macro and this is not
REQUIRE(cnt == 16); REQUIRE(cnt == 16);
``` ```
Because C++11 provides the necessary tools to do this, we are planning We currently do not plan to support thread-safe assertions.
to remove this limitation in the future.
### Process isolation in a test ### Process isolation in a test
Catch does not support running tests in isolated (forked) processes. While this might in the future, the fact that Windows does not support forking and only allows full-on process creation and the desire to keep code as similar as possible across platforms, mean that this is likely to take significant development time, that is not currently available. Catch does not support running tests in isolated (forked) processes. While this might in the future, the fact that Windows does not support forking and only allows full-on process creation and the desire to keep code as similar as possible across platforms, mean that this is likely to take significant development time, that is not currently available.
@@ -155,7 +155,7 @@ with expansion:
### Clang/G++ -- skipping leaf sections after an exception ### Clang/G++ -- skipping leaf sections after an exception
Some versions of `libc++` and `libstdc++` (or their runtimes) have a bug with `std::uncaught_exception()` getting stuck returning `true` after rethrow, even if there are no active exceptions. One such case is this snippet, which skipped the sections "a" and "b", when compiled against `libcxxrt` from master Some versions of `libc++` and `libstdc++` (or their runtimes) have a bug with `std::uncaught_exception()` getting stuck returning `true` after rethrow, even if there are no active exceptions. One such case is this snippet, which skipped the sections "a" and "b", when compiled against `libcxxrt` from the master branch
```cpp ```cpp
#include <catch2/catch_test_macros.hpp> #include <catch2/catch_test_macros.hpp>

View File

@@ -141,18 +141,27 @@ are a permutation of the ones in `some_vec`.
### Floating point matchers ### Floating point matchers
Catch2 provides 3 matchers that target floating point numbers. These Catch2 provides 4 matchers that target floating point numbers. These
are: are:
* `WithinAbs(double target, double margin)`, * `WithinAbs(double target, double margin)`,
* `WithinULP(FloatingPoint target, uint64_t maxUlpDiff)`, and * `WithinULP(FloatingPoint target, uint64_t maxUlpDiff)`, and
* `WithinRel(FloatingPoint target, FloatingPoint eps)`. * `WithinRel(FloatingPoint target, FloatingPoint eps)`.
* `IsNaN()`
> `WithinRel` matcher was introduced in Catch2 2.10.0 > `WithinRel` matcher was introduced in Catch2 2.10.0
For more details, read [the docs on comparing floating point > `IsNaN` matcher was introduced in Catch2 3.3.2.
The first three serve to compare two floating pointe numbers. For more
details about how they work, read [the docs on comparing floating point
numbers](comparing-floating-point-numbers.md#floating-point-matchers). numbers](comparing-floating-point-numbers.md#floating-point-matchers).
`IsNaN` then does exactly what it says on the tin. It matches the input
if it is a NaN (Not a Number). The advantage of using it over just plain
`REQUIRE(std::isnan(x))`, is that if the check fails, with `REQUIRE` you
won't see the value of `x`, but with `REQUIRE_THAT(x, IsNaN())`, you will.
### Miscellaneous matchers ### Miscellaneous matchers
@@ -190,13 +199,23 @@ properties. The macro is `REQUIRE_THROWS_MATCHES(expr, ExceptionType, Matcher)`.
> `REQUIRE_THROWS_MATCHES` macro lives in `catch2/matchers/catch_matchers.hpp` > `REQUIRE_THROWS_MATCHES` macro lives in `catch2/matchers/catch_matchers.hpp`
Catch2 currently provides only one matcher for exceptions, Catch2 currently provides two matchers for exceptions.
`Message(std::string message)`. `Message` checks that the exception's These are:
* `Message(std::string message)`.
* `MessageMatches(Matcher matcher)`.
> `MessageMatches` was [introduced](https://github.com/catchorg/Catch2/pull/2570) in Catch2 3.3.0
`Message` checks that the exception's
message, as returned from `what` is exactly equal to `message`. message, as returned from `what` is exactly equal to `message`.
`MessageMatches` applies the provided matcher on the exception's
message, as returned from `what`. This is useful in conjunctions with the `std::string` matchers (e.g. `StartsWith`)
Example use: Example use:
```cpp ```cpp
REQUIRE_THROWS_MATCHES(throwsDerivedException(), DerivedException, Message("DerivedException::what")); REQUIRE_THROWS_MATCHES(throwsDerivedException(), DerivedException, Message("DerivedException::what"));
REQUIRE_THROWS_MATCHES(throwsDerivedException(), DerivedException, MessageMatches(StartsWith("DerivedException")));
``` ```
Note that `DerivedException` in the example above has to derive from Note that `DerivedException` in the example above has to derive from
@@ -218,11 +237,19 @@ definitions to handle generic range-like types. These are:
* `Contains(T&& target_element, Comparator = std::equal_to<>{})` * `Contains(T&& target_element, Comparator = std::equal_to<>{})`
* `Contains(Matcher element_matcher)` * `Contains(Matcher element_matcher)`
* `AllMatch(Matcher element_matcher)` * `AllMatch(Matcher element_matcher)`
* `NoneMatch(Matcher element_matcher)`
* `AnyMatch(Matcher element_matcher)` * `AnyMatch(Matcher element_matcher)`
* `AllTrue()` * `NoneMatch(Matcher element_matcher)`
* `NoneTrue()` * `AllTrue()`, `AnyTrue()`, `NoneTrue()`
* `AnyTrue()` * `RangeEquals(TargetRangeLike&&, Comparator = std::equal_to<>{})`
* `UnorderedRangeEquals(TargetRangeLike&&, Comparator = std::equal_to<>{})`
> `IsEmpty`, `SizeIs`, `Contains` were introduced in Catch2 3.0.1
> `All/Any/NoneMatch` were introduced in Catch2 3.0.1
> `All/Any/NoneTrue` were introduced in Catch2 3.1.0
> `RangeEquals` and `UnorderedRangeEquals` matchers were [introduced](https://github.com/catchorg/Catch2/pull/2377) in Catch2 3.3.0
`IsEmpty` should be self-explanatory. It successfully matches objects `IsEmpty` should be self-explanatory. It successfully matches objects
that are empty according to either `std::empty`, or ADL-found `empty` that are empty according to either `std::empty`, or ADL-found `empty`
@@ -249,6 +276,25 @@ all, none, or any of the contained elements are `true`, respectively.
It works for ranges of `bool`s and ranges of elements (explicitly) It works for ranges of `bool`s and ranges of elements (explicitly)
convertible to `bool`. convertible to `bool`.
`RangeEquals` compares the range that the matcher is constructed with
(the "target range") against the range to be tested, element-wise. The
match succeeds if all elements from the two ranges compare equal (using
`operator==` by default). The ranges do not need to be the same type,
and the element types do not need to be the same, as long as they are
comparable. (e.g. you may compare `std::vector<int>` to `std::array<char>`).
`UnorderedRangeEquals` is similar to `RangeEquals`, but the order
does not matter. For example "1, 2, 3" would match "3, 2, 1", but not
"1, 1, 2, 3" As with `RangeEquals`, `UnorderedRangeEquals` compares
the individual elements using using `operator==` by default.
Both `RangeEquals` and `UnorderedRangeEquals` optionally accept a
predicate which can be used to compare the containers element-wise.
To check a container elementwise against a given matcher, use
`AllMatch`.
## Writing custom matchers (old style) ## Writing custom matchers (old style)
The old style of writing matchers has been introduced back in Catch The old style of writing matchers has been introduced back in Catch

View File

@@ -2,6 +2,9 @@
# Release notes # Release notes
**Contents**<br> **Contents**<br>
[3.3.2](#332)<br>
[3.3.1](#331)<br>
[3.3.0](#330)<br>
[3.2.1](#321)<br> [3.2.1](#321)<br>
[3.2.0](#320)<br> [3.2.0](#320)<br>
[3.1.1](#311)<br> [3.1.1](#311)<br>
@@ -54,6 +57,67 @@
## 3.3.2
### Improvements
* Further reduced allocations
* The compact, console, TAP and XML reporters perform less allocations in various cases
* Removed 1 allocation per entered `SECTION`/`TEST_CASE`.
* Removed 2 allocations per test case exit, if stdout/stderr is captured
* Improved performance
* Section tracking is 10%-25% faster than in v3.3.0
* Assertion handling is 5%-10% faster than in v3.3.0
* Test case registration is 1%-2% faster than in v3.3.0
* Tiny speedup for registering listeners
* Tiny speedup for `CAPTURE`, `TEST_CASE_METHOD`, `METHOD_AS_TEST_CASE`, and `TEMPLATE_LIST_TEST_*` macros.
* `Contains`, `RangeEquals` and `UnorderedRangeEquals` matchers now support ranges with iterator + sentinel pair
* Added `IsNaN` matcher
* Unlike `REQUIRE(isnan(x))`, `REQUIRE_THAT(x, IsNaN())` shows you the value of `x`.
* Suppressed `declared_but_not_referenced` warning for NVHPC (#2637)
### Fixes
* Fixed performance regression in section tracking introduced in v3.3.1
* Extreme cases would cause the tracking to run about 4x slower than in 3.3.0
## 3.3.1
### Improvements
* Reduced allocations and improved performance
* The exact improvements are dependent on your usage of Catch2.
* For example running Catch2's SelfTest binary performs 8k less allocations.
* The main improvement comes from smarter handling of `SECTION`s, especially sibling `SECTION`s
## 3.3.0
### Improvements
* Added `MessageMatches` exception matcher (#2570)
* Added `RangeEquals` and `UnorderedRangeEquals` generic range matchers (#2377)
* Added `SKIP` macro for skipping tests from within the test body (#2360)
* All built-in reporters have been extended to handle it properly, whether your custom reporter needs changes depends on how it was written
* `skipTest` reporter event **is unrelated** to this, and has been deprecated since it has practically no uses
* Restored support for PPC Macs in the break-into-debugger functionality (#2619)
* Made our warning suppression compatible with CUDA toolkit pre 11.5 (#2626)
* Cleaned out some static analysis complaints
### Fixes
* Fixed macro redefinition warning when NVCC was reporting as MSVC (#2603)
* Fixed throws in generator constructor causing the whole binary to abort (#2615)
* Now it just fails the test
* Fixed missing transitive include with libstdc++13 (#2611)
### Miscellaneous
* Improved support for dynamic library build with non-MSVC compilers on Windows (#2630)
* When used as a subproject, Catch2 keeps its generated header in a separate directory from the main project (#2604)
## 3.2.1 ## 3.2.1
### Improvements ### Improvements

View File

@@ -0,0 +1,129 @@
<a id="top"></a>
# Explicitly skipping, passing, and failing tests at runtime
## Skipping Test Cases at Runtime
> [Introduced](https://github.com/catchorg/Catch2/pull/2360) in Catch2 3.3.0.
In some situations it may not be possible to meaningfully execute a test case,
for example when the system under test is missing certain hardware capabilities.
If the required conditions can only be determined at runtime, it often
doesn't make sense to consider such a test case as either passed or failed,
because it simply can not run at all.
To properly express such scenarios, Catch2 provides a way to explicitly
_skip_ test cases, using the `SKIP` macro:
```
SKIP( [streamable expression] )
```
Example usage:
```c++
TEST_CASE("copy files between drives") {
if(getNumberOfHardDrives() < 2) {
SKIP("at least two hard drives required");
}
// ...
}
```
This test case is then reported as _skipped_ instead of _passed_ or _failed_.
The `SKIP` macro behaves similarly to an explicit [`FAIL`](#passing-and-failing-test-cases),
in that it is the last expression that will be executed:
```c++
TEST_CASE("my test") {
printf("foo");
SKIP();
printf("bar"); // not printed
}
```
However a failed assertion _before_ a `SKIP` still causes the entire
test case to fail:
```c++
TEST_CASE("failing test") {
CHECK(1 == 2);
SKIP();
}
```
### Interaction with Sections and Generators
Sections, nested sections as well as specific outputs from [generators](generators.md#top)
can all be individually skipped, with the rest executing as usual:
```c++
TEST_CASE("complex test case") {
int value = GENERATE(2, 4, 6);
SECTION("a") {
SECTION("a1") { CHECK(value < 8); }
SECTION("a2") {
if (value == 4) {
SKIP();
}
CHECK(value % 2 == 0);
}
}
}
```
This test case will report 5 passing assertions; one for each of the three
values in section `a1`, and then two in section `a2`, from values 2 and 4.
Note that as soon as one section is skipped, the entire test case will
be reported as _skipped_ (unless there is a failing assertion, in which
case the test is handled as _failed_ instead).
Note that if all test cases in a run are skipped, Catch2 returns a non-zero
exit code, same as it does if no test cases have run. This behaviour can
be overridden using the [--allow-running-no-tests](command-line.md#no-tests-override)
flag.
## Passing and failing test cases
Test cases can also be explicitly passed or failed, without the use of
assertions, and with a specific message. This can be useful to handle
complex preconditions/postconditions and give useful error messages
when they fail.
* `SUCCEED( [streamable expression] )`
`SUCCEED` is morally equivalent with `INFO( [streamable expression] ); REQUIRE( true );`.
Note that it does not stop further test execution, so it cannot be used
to guard failing assertions from being executed.
_In practice, `SUCCEED` is usually used as a test placeholder, to avoid
[failing a test case due to missing assertions](command-line.md#warnings)._
```cpp
TEST_CASE( "SUCCEED showcase" ) {
int I = 1;
SUCCEED( "I is " << I );
// ... execution continues here ...
}
```
* `FAIL( [streamable expression] )`
`FAIL` is morally equivalent with `INFO( [streamable expression] ); REQUIRE( false );`.
_In practice, `FAIL` is usually used to stop executing test that is currently
known to be broken, but has to be fixed later._
```cpp
TEST_CASE( "FAIL showcase" ) {
FAIL( "This test case causes segfault, which breaks CI." );
// ... this will not be executed ...
}
```
---
[Home](Readme.md#top)

View File

@@ -25,7 +25,8 @@ _section description_ can be used to provide long form description
of a section while keeping the _section name_ short for use with the of a section while keeping the _section name_ short for use with the
[`-c` command line parameter](command-line.md#specify-the-section-to-run). [`-c` command line parameter](command-line.md#specify-the-section-to-run).
**Test names must be unique within the Catch executable.** **The combination of test names and tags must be unique within the Catch2
executable.**
For examples see the [Tutorial](tutorial.md#top) For examples see the [Tutorial](tutorial.md#top)
@@ -68,7 +69,8 @@ All tag names beginning with non-alphanumeric characters are reserved by Catch.
* `[!nonportable]` - Indicates that behaviour may vary between platforms or compilers. * `[!nonportable]` - Indicates that behaviour may vary between platforms or compilers.
* `[#<filename>]` - running with `-#` or `--filenames-as-tags` causes Catch to add the filename, prefixed with `#` (and with any extension stripped), as a tag to all contained tests, e.g. tests in testfile.cpp would all be tagged `[#testfile]`. * `[#<filename>]` - these tags are added to test cases when you run Catch2
with [`-#` or `--filenames-as-tags`](command-line.md#filenames-as-tags).
* `[@<alias>]` - tag aliases all begin with `@` (see below). * `[@<alias>]` - tag aliases all begin with `@` (see below).
@@ -167,7 +169,11 @@ Other than the additional prefixes and the formatting in the console reporter th
In addition to `TEST_CASE`s, Catch2 also supports test cases parametrised In addition to `TEST_CASE`s, Catch2 also supports test cases parametrised
by types, in the form of `TEMPLATE_TEST_CASE`, by types, in the form of `TEMPLATE_TEST_CASE`,
`TEMPLATE_PRODUCT_TEST_CASE` and `TEMPLATE_LIST_TEST_CASE`. `TEMPLATE_PRODUCT_TEST_CASE` and `TEMPLATE_LIST_TEST_CASE`. These macros
are defined in the `catch_template_test_macros.hpp` header, so compiling
the code examples below also requires
`#include <catch2/catch_template_test_macros.hpp>`.
* **TEMPLATE_TEST_CASE(** _test name_ , _tags_, _type1_, _type2_, ..., _typen_ **)** * **TEMPLATE_TEST_CASE(** _test name_ , _tags_, _type1_, _type2_, ..., _typen_ **)**
@@ -289,7 +295,9 @@ TEMPLATE_LIST_TEST_CASE("Template test case with test types specified inside std
In addition to [type parametrised test cases](#type-parametrised-test-cases) Catch2 also supports In addition to [type parametrised test cases](#type-parametrised-test-cases) Catch2 also supports
signature base parametrised test cases, in form of `TEMPLATE_TEST_CASE_SIG` and `TEMPLATE_PRODUCT_TEST_CASE_SIG`. signature base parametrised test cases, in form of `TEMPLATE_TEST_CASE_SIG` and `TEMPLATE_PRODUCT_TEST_CASE_SIG`.
These test cases have similar syntax like [type parametrised test cases](#type-parametrised-test-cases), with one These test cases have similar syntax like [type parametrised test cases](#type-parametrised-test-cases), with one
additional positional argument which specifies the signature. additional positional argument which specifies the signature. These macros are defined in the
`catch_template_test_macros.hpp` header, so compiling the code examples below also requires
`#include <catch2/catch_template_test_macros.hpp>`.
### Signature ### Signature
Signature has some strict rules for these tests cases to work properly: Signature has some strict rules for these tests cases to work properly:

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

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

View File

@@ -39,7 +39,7 @@ set(BENCHMARK_FILES ${BENCHMARK_HEADERS} ${BENCHMARK_SOURCES})
set(IMPL_HEADERS set(IMPL_HEADERS
"${CMAKE_BINARY_DIR}/generated-includes/catch2/catch_user_config.hpp" "${PROJECT_BINARY_DIR}/generated-includes/catch2/catch_user_config.hpp"
${SOURCES_DIR}/catch_user_config.hpp.in ${SOURCES_DIR}/catch_user_config.hpp.in
${SOURCES_DIR}/catch_all.hpp ${SOURCES_DIR}/catch_all.hpp
${SOURCES_DIR}/catch_approx.hpp ${SOURCES_DIR}/catch_approx.hpp
@@ -88,6 +88,7 @@ set(IMPL_HEADERS
${SOURCES_DIR}/internal/catch_floating_point_helpers.hpp ${SOURCES_DIR}/internal/catch_floating_point_helpers.hpp
${SOURCES_DIR}/internal/catch_getenv.hpp ${SOURCES_DIR}/internal/catch_getenv.hpp
${SOURCES_DIR}/internal/catch_istream.hpp ${SOURCES_DIR}/internal/catch_istream.hpp
${SOURCES_DIR}/internal/catch_is_permutation.hpp
${SOURCES_DIR}/internal/catch_lazy_expr.hpp ${SOURCES_DIR}/internal/catch_lazy_expr.hpp
${SOURCES_DIR}/internal/catch_leak_detector.hpp ${SOURCES_DIR}/internal/catch_leak_detector.hpp
${SOURCES_DIR}/internal/catch_list.hpp ${SOURCES_DIR}/internal/catch_list.hpp
@@ -252,6 +253,7 @@ set(MATCHER_HEADERS
${SOURCES_DIR}/matchers/catch_matchers_all.hpp ${SOURCES_DIR}/matchers/catch_matchers_all.hpp
${SOURCES_DIR}/matchers/catch_matchers_container_properties.hpp ${SOURCES_DIR}/matchers/catch_matchers_container_properties.hpp
${SOURCES_DIR}/matchers/catch_matchers_contains.hpp ${SOURCES_DIR}/matchers/catch_matchers_contains.hpp
${SOURCES_DIR}/matchers/catch_matchers_range_equals.hpp
${SOURCES_DIR}/matchers/catch_matchers_exception.hpp ${SOURCES_DIR}/matchers/catch_matchers_exception.hpp
${SOURCES_DIR}/matchers/catch_matchers_floating_point.hpp ${SOURCES_DIR}/matchers/catch_matchers_floating_point.hpp
${SOURCES_DIR}/matchers/catch_matchers_predicate.hpp ${SOURCES_DIR}/matchers/catch_matchers_predicate.hpp
@@ -321,7 +323,7 @@ set(ALL_FILES
) )
set(FILTERED_FILES ${ALL_FILES}) set(FILTERED_FILES ${ALL_FILES})
list(REMOVE_ITEM FILTERED_FILES "${CMAKE_BINARY_DIR}/generated-includes/catch2/catch_user_config.hpp") list(REMOVE_ITEM FILTERED_FILES "${PROJECT_BINARY_DIR}/generated-includes/catch2/catch_user_config.hpp")
source_group( source_group(
TREE ${SOURCES_DIR} TREE ${SOURCES_DIR}
PREFIX sources PREFIX sources
@@ -329,7 +331,7 @@ source_group(
) )
source_group("generated headers" source_group("generated headers"
FILES FILES
"${CMAKE_BINARY_DIR}/generated-includes/catch2/catch_user_config.hpp" "${PROJECT_BINARY_DIR}/generated-includes/catch2/catch_user_config.hpp"
) )
add_library(Catch2 ${ALL_FILES}) add_library(Catch2 ${ALL_FILES})
@@ -372,13 +374,13 @@ target_compile_features(Catch2
configure_file( configure_file(
"${SOURCES_DIR}/catch_user_config.hpp.in" "${SOURCES_DIR}/catch_user_config.hpp.in"
"${CMAKE_BINARY_DIR}/generated-includes/catch2/catch_user_config.hpp" "${PROJECT_BINARY_DIR}/generated-includes/catch2/catch_user_config.hpp"
) )
target_include_directories(Catch2 target_include_directories(Catch2
PUBLIC PUBLIC
$<BUILD_INTERFACE:${SOURCES_DIR}/..> $<BUILD_INTERFACE:${SOURCES_DIR}/..>
$<BUILD_INTERFACE:${CMAKE_BINARY_DIR}/generated-includes> $<BUILD_INTERFACE:${PROJECT_BINARY_DIR}/generated-includes>
$<INSTALL_INTERFACE:${CMAKE_INSTALL_INCLUDEDIR}> $<INSTALL_INTERFACE:${CMAKE_INSTALL_INCLUDEDIR}>
) )
@@ -426,7 +428,7 @@ if (NOT_SUBPROJECT)
install( install(
DIRECTORY DIRECTORY
"${SOURCES_DIR}" "${SOURCES_DIR}"
"${CMAKE_BINARY_DIR}/generated-includes/catch2" # Also install the generated header "${PROJECT_BINARY_DIR}/generated-includes/catch2" # Also install the generated header
DESTINATION DESTINATION
"${CMAKE_INSTALL_INCLUDEDIR}" "${CMAKE_INSTALL_INCLUDEDIR}"
FILES_MATCHING FILES_MATCHING
@@ -447,7 +449,7 @@ if (CATCH_BUILD_EXAMPLES OR CATCH_BUILD_EXTRA_TESTS)
target_include_directories(Catch2_buildall_interface target_include_directories(Catch2_buildall_interface
INTERFACE INTERFACE
$<BUILD_INTERFACE:${SOURCES_DIR}/..> $<BUILD_INTERFACE:${SOURCES_DIR}/..>
$<BUILD_INTERFACE:${CMAKE_BINARY_DIR}/generated-includes> $<BUILD_INTERFACE:${PROJECT_BINARY_DIR}/generated-includes>
$<INSTALL_INTERFACE:${CMAKE_INSTALL_INCLUDEDIR}> $<INSTALL_INTERFACE:${CMAKE_INSTALL_INCLUDEDIR}>
) )
target_compile_definitions(Catch2_buildall_interface target_compile_definitions(Catch2_buildall_interface
@@ -487,12 +489,10 @@ set(CATCH_WARNING_TARGETS ${CATCH_WARNING_TARGETS} PARENT_SCOPE)
# so we want to check & warn users if they do this. However, we won't abort # so we want to check & warn users if they do this. However, we won't abort
# the configuration step so that we don't have to also provide an override. # the configuration step so that we don't have to also provide an override.
if (BUILD_SHARED_LIBS) if (BUILD_SHARED_LIBS)
if (MSVC) set_target_properties(Catch2 Catch2WithMain
set_target_properties(Catch2 Catch2WithMain PROPERTIES
PROPERTIES WINDOWS_EXPORT_ALL_SYMBOLS ON
WINDOWS_EXPORT_ALL_SYMBOLS ON )
)
endif()
get_target_property(_VisPreset Catch2 CXX_VISIBILITY_PRESET) get_target_property(_VisPreset Catch2 CXX_VISIBILITY_PRESET)
if (NOT MSVC AND _VisPreset STREQUAL "hidden") if (NOT MSVC AND _VisPreset STREQUAL "hidden")

View File

@@ -64,7 +64,7 @@ namespace Catch {
}); });
BenchmarkInfo info { BenchmarkInfo info {
name, CATCH_MOVE(name),
plan.estimated_duration.count(), plan.estimated_duration.count(),
plan.iterations_per_sample, plan.iterations_per_sample,
cfg->benchmarkSamples(), cfg->benchmarkSamples(),
@@ -80,7 +80,7 @@ namespace Catch {
}); });
auto analysis = Detail::analyse(*cfg, env, samples.begin(), samples.end()); auto analysis = Detail::analyse(*cfg, env, samples.begin(), samples.end());
BenchmarkStats<FloatDuration<Clock>> stats{ info, analysis.samples, analysis.mean, analysis.standard_deviation, analysis.outliers, analysis.outlier_variance }; BenchmarkStats<FloatDuration<Clock>> stats{ CATCH_MOVE(info), CATCH_MOVE(analysis.samples), analysis.mean, analysis.standard_deviation, analysis.outliers, analysis.outlier_variance };
getResultCapture().benchmarkEnded(stats); getResultCapture().benchmarkEnded(stats);
} CATCH_CATCH_ANON (TestFailureException) { } CATCH_CATCH_ANON (TestFailureException) {
getResultCapture().benchmarkFailed("Benchmark failed due to failed assertion"_sr); getResultCapture().benchmarkFailed("Benchmark failed due to failed assertion"_sr);

View File

@@ -70,6 +70,7 @@
#include <catch2/internal/catch_fatal_condition_handler.hpp> #include <catch2/internal/catch_fatal_condition_handler.hpp>
#include <catch2/internal/catch_floating_point_helpers.hpp> #include <catch2/internal/catch_floating_point_helpers.hpp>
#include <catch2/internal/catch_getenv.hpp> #include <catch2/internal/catch_getenv.hpp>
#include <catch2/internal/catch_is_permutation.hpp>
#include <catch2/internal/catch_istream.hpp> #include <catch2/internal/catch_istream.hpp>
#include <catch2/internal/catch_lazy_expr.hpp> #include <catch2/internal/catch_lazy_expr.hpp>
#include <catch2/internal/catch_leak_detector.hpp> #include <catch2/internal/catch_leak_detector.hpp>

View File

@@ -7,6 +7,7 @@
// SPDX-License-Identifier: BSL-1.0 // SPDX-License-Identifier: BSL-1.0
#include <catch2/catch_assertion_result.hpp> #include <catch2/catch_assertion_result.hpp>
#include <catch2/internal/catch_reusable_string_stream.hpp> #include <catch2/internal/catch_reusable_string_stream.hpp>
#include <catch2/internal/catch_move_and_forward.hpp>
namespace Catch { namespace Catch {
@@ -26,9 +27,9 @@ namespace Catch {
return reconstructedExpression; return reconstructedExpression;
} }
AssertionResult::AssertionResult( AssertionInfo const& info, AssertionResultData const& data ) AssertionResult::AssertionResult( AssertionInfo const& info, AssertionResultData&& data )
: m_info( info ), : m_info( info ),
m_resultData( data ) m_resultData( CATCH_MOVE(data) )
{} {}
// Result was a success // Result was a success
@@ -67,16 +68,15 @@ namespace Catch {
} }
std::string AssertionResult::getExpressionInMacro() const { std::string AssertionResult::getExpressionInMacro() const {
std::string expr; if ( m_info.macroName.empty() ) {
if( m_info.macroName.empty() ) return static_cast<std::string>( m_info.capturedExpression );
expr = static_cast<std::string>(m_info.capturedExpression);
else {
expr.reserve( m_info.macroName.size() + m_info.capturedExpression.size() + 4 );
expr += m_info.macroName;
expr += "( ";
expr += m_info.capturedExpression;
expr += " )";
} }
std::string expr;
expr.reserve( m_info.macroName.size() + m_info.capturedExpression.size() + 4 );
expr += m_info.macroName;
expr += "( ";
expr += m_info.capturedExpression;
expr += " )";
return expr; return expr;
} }

View File

@@ -35,7 +35,7 @@ namespace Catch {
class AssertionResult { class AssertionResult {
public: public:
AssertionResult() = delete; AssertionResult() = delete;
AssertionResult( AssertionInfo const& info, AssertionResultData const& data ); AssertionResult( AssertionInfo const& info, AssertionResultData&& data );
bool isOk() const; bool isOk() const;
bool succeeded() const; bool succeeded() const;

View File

@@ -19,8 +19,8 @@ namespace Catch {
//////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////
ScopedMessage::ScopedMessage( MessageBuilder const& builder ): ScopedMessage::ScopedMessage( MessageBuilder&& builder ):
m_info( builder.m_info ) { m_info( CATCH_MOVE(builder.m_info) ) {
m_info.message = builder.m_stream.str(); m_info.message = builder.m_stream.str();
getResultCapture().pushScopedMessage( m_info ); getResultCapture().pushScopedMessage( m_info );
} }

View File

@@ -39,11 +39,10 @@ namespace Catch {
ResultWas::OfType type ): ResultWas::OfType type ):
m_info(macroName, lineInfo, type) {} m_info(macroName, lineInfo, type) {}
template<typename T> template<typename T>
MessageBuilder& operator << ( T const& value ) { MessageBuilder&& operator << ( T const& value ) && {
m_stream << value; m_stream << value;
return *this; return CATCH_MOVE(*this);
} }
MessageInfo m_info; MessageInfo m_info;
@@ -51,7 +50,7 @@ namespace Catch {
class ScopedMessage { class ScopedMessage {
public: public:
explicit ScopedMessage( MessageBuilder const& builder ); explicit ScopedMessage( MessageBuilder&& builder );
ScopedMessage( ScopedMessage& duplicate ) = delete; ScopedMessage( ScopedMessage& duplicate ) = delete;
ScopedMessage( ScopedMessage&& old ) noexcept; ScopedMessage( ScopedMessage&& old ) noexcept;
~ScopedMessage(); ~ScopedMessage();
@@ -98,7 +97,10 @@ namespace Catch {
/////////////////////////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////////////////////////
#define INTERNAL_CATCH_CAPTURE( varName, macroName, ... ) \ #define INTERNAL_CATCH_CAPTURE( varName, macroName, ... ) \
Catch::Capturer varName( macroName, CATCH_INTERNAL_LINEINFO, Catch::ResultWas::Info, #__VA_ARGS__ ); \ Catch::Capturer varName( macroName##_catch_sr, \
CATCH_INTERNAL_LINEINFO, \
Catch::ResultWas::Info, \
#__VA_ARGS__##_catch_sr ); \
varName.captureValues( 0, __VA_ARGS__ ) varName.captureValues( 0, __VA_ARGS__ )
/////////////////////////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////////////////////////

View File

@@ -341,6 +341,12 @@ namespace Catch {
return 2; return 2;
} }
if ( totals.testCases.total() > 0 &&
totals.testCases.total() == totals.testCases.skipped
&& !m_config->zeroTestsCountAsSuccess() ) {
return 4;
}
// Note that on unices only the lower 8 bits are usually used, clamping // Note that on unices only the lower 8 bits are usually used, clamping
// the return value to 255 prevents false negative when some multiple // the return value to 255 prevents false negative when some multiple
// of 256 tests has failed // of 256 tests has failed

View File

@@ -15,6 +15,7 @@
#include <catch2/internal/catch_unique_ptr.hpp> #include <catch2/internal/catch_unique_ptr.hpp>
#include <cstdint>
#include <string> #include <string>
#include <vector> #include <vector>

View File

@@ -49,6 +49,7 @@
#define CATCH_FAIL( ... ) INTERNAL_CATCH_MSG( "CATCH_FAIL", Catch::ResultWas::ExplicitFailure, Catch::ResultDisposition::Normal, __VA_ARGS__ ) #define CATCH_FAIL( ... ) INTERNAL_CATCH_MSG( "CATCH_FAIL", Catch::ResultWas::ExplicitFailure, Catch::ResultDisposition::Normal, __VA_ARGS__ )
#define CATCH_FAIL_CHECK( ... ) INTERNAL_CATCH_MSG( "CATCH_FAIL_CHECK", Catch::ResultWas::ExplicitFailure, Catch::ResultDisposition::ContinueOnFailure, __VA_ARGS__ ) #define CATCH_FAIL_CHECK( ... ) INTERNAL_CATCH_MSG( "CATCH_FAIL_CHECK", Catch::ResultWas::ExplicitFailure, Catch::ResultDisposition::ContinueOnFailure, __VA_ARGS__ )
#define CATCH_SUCCEED( ... ) INTERNAL_CATCH_MSG( "CATCH_SUCCEED", Catch::ResultWas::Ok, Catch::ResultDisposition::ContinueOnFailure, __VA_ARGS__ ) #define CATCH_SUCCEED( ... ) INTERNAL_CATCH_MSG( "CATCH_SUCCEED", Catch::ResultWas::Ok, Catch::ResultDisposition::ContinueOnFailure, __VA_ARGS__ )
#define CATCH_SKIP( ... ) INTERNAL_CATCH_MSG( "SKIP", Catch::ResultWas::ExplicitSkip, Catch::ResultDisposition::Normal, __VA_ARGS__ )
#if !defined(CATCH_CONFIG_RUNTIME_STATIC_REQUIRE) #if !defined(CATCH_CONFIG_RUNTIME_STATIC_REQUIRE)
@@ -102,6 +103,7 @@
#define CATCH_FAIL( ... ) (void)(0) #define CATCH_FAIL( ... ) (void)(0)
#define CATCH_FAIL_CHECK( ... ) (void)(0) #define CATCH_FAIL_CHECK( ... ) (void)(0)
#define CATCH_SUCCEED( ... ) (void)(0) #define CATCH_SUCCEED( ... ) (void)(0)
#define CATCH_SKIP( ... ) (void)(0)
#define CATCH_STATIC_REQUIRE( ... ) (void)(0) #define CATCH_STATIC_REQUIRE( ... ) (void)(0)
#define CATCH_STATIC_REQUIRE_FALSE( ... ) (void)(0) #define CATCH_STATIC_REQUIRE_FALSE( ... ) (void)(0)
@@ -146,6 +148,7 @@
#define FAIL( ... ) INTERNAL_CATCH_MSG( "FAIL", Catch::ResultWas::ExplicitFailure, Catch::ResultDisposition::Normal, __VA_ARGS__ ) #define FAIL( ... ) INTERNAL_CATCH_MSG( "FAIL", Catch::ResultWas::ExplicitFailure, Catch::ResultDisposition::Normal, __VA_ARGS__ )
#define FAIL_CHECK( ... ) INTERNAL_CATCH_MSG( "FAIL_CHECK", Catch::ResultWas::ExplicitFailure, Catch::ResultDisposition::ContinueOnFailure, __VA_ARGS__ ) #define FAIL_CHECK( ... ) INTERNAL_CATCH_MSG( "FAIL_CHECK", Catch::ResultWas::ExplicitFailure, Catch::ResultDisposition::ContinueOnFailure, __VA_ARGS__ )
#define SUCCEED( ... ) INTERNAL_CATCH_MSG( "SUCCEED", Catch::ResultWas::Ok, Catch::ResultDisposition::ContinueOnFailure, __VA_ARGS__ ) #define SUCCEED( ... ) INTERNAL_CATCH_MSG( "SUCCEED", Catch::ResultWas::Ok, Catch::ResultDisposition::ContinueOnFailure, __VA_ARGS__ )
#define SKIP( ... ) INTERNAL_CATCH_MSG( "SKIP", Catch::ResultWas::ExplicitSkip, Catch::ResultDisposition::Normal, __VA_ARGS__ )
#if !defined(CATCH_CONFIG_RUNTIME_STATIC_REQUIRE) #if !defined(CATCH_CONFIG_RUNTIME_STATIC_REQUIRE)
@@ -198,6 +201,7 @@
#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 SKIP( ... ) (void)(0)
#define STATIC_REQUIRE( ... ) (void)(0) #define STATIC_REQUIRE( ... ) (void)(0)
#define STATIC_REQUIRE_FALSE( ... ) (void)(0) #define STATIC_REQUIRE_FALSE( ... ) (void)(0)

View File

@@ -14,6 +14,7 @@ namespace Catch {
diff.passed = passed - other.passed; diff.passed = passed - other.passed;
diff.failed = failed - other.failed; diff.failed = failed - other.failed;
diff.failedButOk = failedButOk - other.failedButOk; diff.failedButOk = failedButOk - other.failedButOk;
diff.skipped = skipped - other.skipped;
return diff; return diff;
} }
@@ -21,14 +22,15 @@ namespace Catch {
passed += other.passed; passed += other.passed;
failed += other.failed; failed += other.failed;
failedButOk += other.failedButOk; failedButOk += other.failedButOk;
skipped += other.skipped;
return *this; return *this;
} }
std::uint64_t Counts::total() const { std::uint64_t Counts::total() const {
return passed + failed + failedButOk; return passed + failed + failedButOk + skipped;
} }
bool Counts::allPassed() const { bool Counts::allPassed() const {
return failed == 0 && failedButOk == 0; return failed == 0 && failedButOk == 0 && skipped == 0;
} }
bool Counts::allOk() const { bool Counts::allOk() const {
return failed == 0; return failed == 0;
@@ -53,6 +55,8 @@ namespace Catch {
++diff.testCases.failed; ++diff.testCases.failed;
else if( diff.assertions.failedButOk > 0 ) else if( diff.assertions.failedButOk > 0 )
++diff.testCases.failedButOk; ++diff.testCases.failedButOk;
else if ( diff.assertions.skipped > 0 )
++ diff.testCases.skipped;
else else
++diff.testCases.passed; ++diff.testCases.passed;
return diff; return diff;

View File

@@ -23,6 +23,7 @@ namespace Catch {
std::uint64_t passed = 0; std::uint64_t passed = 0;
std::uint64_t failed = 0; std::uint64_t failed = 0;
std::uint64_t failedButOk = 0; std::uint64_t failedButOk = 0;
std::uint64_t skipped = 0;
}; };
struct Totals { struct Totals {

View File

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

View File

@@ -9,7 +9,7 @@
#define CATCH_VERSION_MACROS_HPP_INCLUDED #define CATCH_VERSION_MACROS_HPP_INCLUDED
#define CATCH_VERSION_MAJOR 3 #define CATCH_VERSION_MAJOR 3
#define CATCH_VERSION_MINOR 2 #define CATCH_VERSION_MINOR 3
#define CATCH_VERSION_PATCH 1 #define CATCH_VERSION_PATCH 2
#endif // CATCH_VERSION_MACROS_HPP_INCLUDED #endif // CATCH_VERSION_MACROS_HPP_INCLUDED

View File

@@ -27,9 +27,16 @@ namespace Detail {
GeneratorUntypedBase::~GeneratorUntypedBase() = default; GeneratorUntypedBase::~GeneratorUntypedBase() = default;
auto acquireGeneratorTracker(StringRef generatorName, SourceLineInfo const& lineInfo ) -> IGeneratorTracker& { IGeneratorTracker* acquireGeneratorTracker(StringRef generatorName, SourceLineInfo const& lineInfo ) {
return getResultCapture().acquireGeneratorTracker( generatorName, lineInfo ); return getResultCapture().acquireGeneratorTracker( generatorName, lineInfo );
} }
IGeneratorTracker* createGeneratorTracker( StringRef generatorName,
SourceLineInfo lineInfo,
GeneratorBasePtr&& generator ) {
return getResultCapture().createGeneratorTracker(
generatorName, lineInfo, CATCH_MOVE( generator ) );
}
} // namespace Generators } // namespace Generators
} // namespace Catch } // namespace Catch

View File

@@ -14,7 +14,6 @@
#include <catch2/internal/catch_stringref.hpp> #include <catch2/internal/catch_stringref.hpp>
#include <catch2/internal/catch_move_and_forward.hpp> #include <catch2/internal/catch_move_and_forward.hpp>
#include <catch2/internal/catch_unique_name.hpp> #include <catch2/internal/catch_unique_name.hpp>
#include <catch2/internal/catch_preprocessor.hpp>
#include <vector> #include <vector>
#include <tuple> #include <tuple>
@@ -204,37 +203,47 @@ namespace Detail {
return makeGenerators( value( T( CATCH_FORWARD( val ) ) ), CATCH_FORWARD( moreGenerators )... ); return makeGenerators( value( T( CATCH_FORWARD( val ) ) ), CATCH_FORWARD( moreGenerators )... );
} }
auto acquireGeneratorTracker( StringRef generatorName, SourceLineInfo const& lineInfo ) -> IGeneratorTracker&; IGeneratorTracker* acquireGeneratorTracker( StringRef generatorName,
SourceLineInfo const& lineInfo );
IGeneratorTracker* createGeneratorTracker( StringRef generatorName,
SourceLineInfo lineInfo,
GeneratorBasePtr&& generator );
template<typename L> template<typename L>
// Note: The type after -> is weird, because VS2015 cannot parse auto generate( StringRef generatorName, SourceLineInfo const& lineInfo, L const& generatorExpression ) -> typename decltype(generatorExpression())::type {
// the expression used in the typedef inside, when it is in
// return type. Yeah.
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( generatorName, lineInfo ); IGeneratorTracker* tracker = acquireGeneratorTracker( generatorName, lineInfo );
if (!tracker.hasGenerator()) { // Creation of tracker is delayed after generator creation, so
tracker.setGenerator(Catch::Detail::make_unique<Generators<UnderlyingType>>(generatorExpression())); // that constructing generator can fail without breaking everything.
if (!tracker) {
tracker = createGeneratorTracker(
generatorName,
lineInfo,
Catch::Detail::make_unique<Generators<UnderlyingType>>(
generatorExpression() ) );
} }
auto const& generator = static_cast<IGenerator<UnderlyingType> const&>( *tracker.getGenerator() ); auto const& generator = static_cast<IGenerator<UnderlyingType> const&>( *tracker->getGenerator() );
return generator.get(); return generator.get();
} }
} // namespace Generators } // namespace Generators
} // namespace Catch } // namespace Catch
#define CATCH_INTERNAL_GENERATOR_STRINGIZE_IMPL( ... ) #__VA_ARGS__##_catch_sr
#define CATCH_INTERNAL_GENERATOR_STRINGIZE(...) CATCH_INTERNAL_GENERATOR_STRINGIZE_IMPL(__VA_ARGS__)
#define GENERATE( ... ) \ #define GENERATE( ... ) \
Catch::Generators::generate( INTERNAL_CATCH_STRINGIZE(INTERNAL_CATCH_UNIQUE_NAME(generator)), \ Catch::Generators::generate( CATCH_INTERNAL_GENERATOR_STRINGIZE(INTERNAL_CATCH_UNIQUE_NAME(generator)), \
CATCH_INTERNAL_LINEINFO, \ CATCH_INTERNAL_LINEINFO, \
[ ]{ using namespace Catch::Generators; return makeGenerators( __VA_ARGS__ ); } ) //NOLINT(google-build-using-namespace) [ ]{ using namespace Catch::Generators; return makeGenerators( __VA_ARGS__ ); } ) //NOLINT(google-build-using-namespace)
#define GENERATE_COPY( ... ) \ #define GENERATE_COPY( ... ) \
Catch::Generators::generate( INTERNAL_CATCH_STRINGIZE(INTERNAL_CATCH_UNIQUE_NAME(generator)), \ Catch::Generators::generate( CATCH_INTERNAL_GENERATOR_STRINGIZE(INTERNAL_CATCH_UNIQUE_NAME(generator)), \
CATCH_INTERNAL_LINEINFO, \ CATCH_INTERNAL_LINEINFO, \
[=]{ using namespace Catch::Generators; return makeGenerators( __VA_ARGS__ ); } ) //NOLINT(google-build-using-namespace) [=]{ using namespace Catch::Generators; return makeGenerators( __VA_ARGS__ ); } ) //NOLINT(google-build-using-namespace)
#define GENERATE_REF( ... ) \ #define GENERATE_REF( ... ) \
Catch::Generators::generate( INTERNAL_CATCH_STRINGIZE(INTERNAL_CATCH_UNIQUE_NAME(generator)), \ Catch::Generators::generate( CATCH_INTERNAL_GENERATOR_STRINGIZE(INTERNAL_CATCH_UNIQUE_NAME(generator)), \
CATCH_INTERNAL_LINEINFO, \ CATCH_INTERNAL_LINEINFO, \
[&]{ using namespace Catch::Generators; return makeGenerators( __VA_ARGS__ ); } ) //NOLINT(google-build-using-namespace) [&]{ using namespace Catch::Generators; return makeGenerators( __VA_ARGS__ ); } ) //NOLINT(google-build-using-namespace)

View File

@@ -13,6 +13,7 @@
#include <catch2/internal/catch_stringref.hpp> #include <catch2/internal/catch_stringref.hpp>
#include <catch2/internal/catch_result_type.hpp> #include <catch2/internal/catch_result_type.hpp>
#include <catch2/internal/catch_unique_ptr.hpp>
namespace Catch { namespace Catch {
@@ -33,16 +34,29 @@ namespace Catch {
template <typename Duration = std::chrono::duration<double, std::nano>> template <typename Duration = std::chrono::duration<double, std::nano>>
struct BenchmarkStats; struct BenchmarkStats;
namespace Generators {
class GeneratorUntypedBase;
using GeneratorBasePtr = Catch::Detail::unique_ptr<GeneratorUntypedBase>;
}
class IResultCapture { class IResultCapture {
public: public:
virtual ~IResultCapture(); virtual ~IResultCapture();
virtual bool sectionStarted( SectionInfo const& sectionInfo, virtual bool sectionStarted( StringRef sectionName,
Counts& assertions ) = 0; SourceLineInfo const& sectionLineInfo,
virtual void sectionEnded( SectionEndInfo const& endInfo ) = 0; Counts& assertions ) = 0;
virtual void sectionEndedEarly( SectionEndInfo const& endInfo ) = 0; virtual void sectionEnded( SectionEndInfo&& endInfo ) = 0;
virtual void sectionEndedEarly( SectionEndInfo&& endInfo ) = 0;
virtual auto acquireGeneratorTracker( StringRef generatorName, SourceLineInfo const& lineInfo ) -> IGeneratorTracker& = 0; virtual IGeneratorTracker*
acquireGeneratorTracker( StringRef generatorName,
SourceLineInfo const& lineInfo ) = 0;
virtual IGeneratorTracker*
createGeneratorTracker( StringRef generatorName,
SourceLineInfo lineInfo,
Generators::GeneratorBasePtr&& generator ) = 0;
virtual void benchmarkPreparing( StringRef name ) = 0; virtual void benchmarkPreparing( StringRef name ) = 0;
virtual void benchmarkStarting( BenchmarkInfo const& info ) = 0; virtual void benchmarkStarting( BenchmarkInfo const& info ) = 0;
@@ -52,7 +66,7 @@ namespace Catch {
virtual void pushScopedMessage( MessageInfo const& message ) = 0; virtual void pushScopedMessage( MessageInfo const& message ) = 0;
virtual void popScopedMessage( MessageInfo const& message ) = 0; virtual void popScopedMessage( MessageInfo const& message ) = 0;
virtual void emplaceUnscopedMessage( MessageBuilder const& builder ) = 0; virtual void emplaceUnscopedMessage( MessageBuilder&& builder ) = 0;
virtual void handleFatalErrorCondition( StringRef message ) = 0; virtual void handleFatalErrorCondition( StringRef message ) = 0;

View File

@@ -60,18 +60,17 @@ namespace Catch {
// Copy message into messages list. // Copy message into messages list.
// !TBD This should have been done earlier, somewhere // !TBD This should have been done earlier, somewhere
MessageBuilder builder( assertionResult.getTestMacroName(), assertionResult.getSourceInfo(), assertionResult.getResultType() ); MessageBuilder builder( assertionResult.getTestMacroName(), assertionResult.getSourceInfo(), assertionResult.getResultType() );
builder << assertionResult.getMessage(); builder.m_info.message = static_cast<std::string>(assertionResult.getMessage());
builder.m_info.message = builder.m_stream.str();
infoMessages.push_back( builder.m_info ); infoMessages.push_back( CATCH_MOVE(builder.m_info) );
} }
} }
SectionStats::SectionStats( SectionInfo const& _sectionInfo, SectionStats::SectionStats( SectionInfo&& _sectionInfo,
Counts const& _assertions, Counts const& _assertions,
double _durationInSeconds, double _durationInSeconds,
bool _missingAssertions ) bool _missingAssertions )
: sectionInfo( _sectionInfo ), : sectionInfo( CATCH_MOVE(_sectionInfo) ),
assertions( _assertions ), assertions( _assertions ),
durationInSeconds( _durationInSeconds ), durationInSeconds( _durationInSeconds ),
missingAssertions( _missingAssertions ) missingAssertions( _missingAssertions )
@@ -80,13 +79,13 @@ namespace Catch {
TestCaseStats::TestCaseStats( TestCaseInfo const& _testInfo, TestCaseStats::TestCaseStats( TestCaseInfo const& _testInfo,
Totals const& _totals, Totals const& _totals,
std::string const& _stdOut, std::string&& _stdOut,
std::string const& _stdErr, std::string&& _stdErr,
bool _aborting ) bool _aborting )
: testInfo( &_testInfo ), : testInfo( &_testInfo ),
totals( _totals ), totals( _totals ),
stdOut( _stdOut ), stdOut( CATCH_MOVE(_stdOut) ),
stdErr( _stdErr ), stdErr( CATCH_MOVE(_stdErr) ),
aborting( _aborting ) aborting( _aborting )
{} {}

View File

@@ -78,7 +78,7 @@ namespace Catch {
}; };
struct SectionStats { struct SectionStats {
SectionStats( SectionInfo const& _sectionInfo, SectionStats( SectionInfo&& _sectionInfo,
Counts const& _assertions, Counts const& _assertions,
double _durationInSeconds, double _durationInSeconds,
bool _missingAssertions ); bool _missingAssertions );
@@ -92,8 +92,8 @@ namespace Catch {
struct TestCaseStats { struct TestCaseStats {
TestCaseStats( TestCaseInfo const& _testInfo, TestCaseStats( TestCaseInfo const& _testInfo,
Totals const& _totals, Totals const& _totals,
std::string const& _stdOut, std::string&& _stdOut,
std::string const& _stdErr, std::string&& _stdErr,
bool _aborting ); bool _aborting );
TestCaseInfo const * testInfo; TestCaseInfo const * testInfo;
@@ -242,7 +242,12 @@ namespace Catch {
*/ */
virtual void testRunEnded( TestRunStats const& testRunStats ) = 0; virtual void testRunEnded( TestRunStats const& testRunStats ) = 0;
//! Called with test cases that are skipped due to the test run aborting /**
* Called with test cases that are skipped due to the test run aborting.
* NOT called for test cases that are explicitly skipped using the `SKIP` macro.
*
* Deprecated - will be removed in the next major release.
*/
virtual void skipTest( TestCaseInfo const& testInfo ) = 0; virtual void skipTest( TestCaseInfo const& testInfo ) = 0;
//! Called if a fatal error (signal/structured exception) occured //! Called if a fatal error (signal/structured exception) occured

View File

@@ -50,6 +50,13 @@ namespace Catch {
if (m_reaction.shouldThrow) { if (m_reaction.shouldThrow) {
throw_test_failure_exception(); throw_test_failure_exception();
} }
if ( m_reaction.shouldSkip ) {
#if !defined( CATCH_CONFIG_DISABLE_EXCEPTIONS )
throw Catch::TestSkipException();
#else
CATCH_ERROR( "Explicitly skipping tests during runtime requires exceptions" );
#endif
}
} }
void AssertionHandler::setCompleted() { void AssertionHandler::setCompleted() {
m_completed = true; m_completed = true;

View File

@@ -22,6 +22,7 @@ namespace Catch {
struct AssertionReaction { struct AssertionReaction {
bool shouldDebugBreak = false; bool shouldDebugBreak = false;
bool shouldThrow = false; bool shouldThrow = false;
bool shouldSkip = false;
}; };
class AssertionHandler { class AssertionHandler {

View File

@@ -41,7 +41,7 @@
// Only GCC compiler should be used in this block, so other compilers trying to // Only GCC compiler should be used in this block, so other compilers trying to
// mask themselves as GCC should be ignored. // mask themselves as GCC should be ignored.
#if defined(__GNUC__) && !defined(__clang__) && !defined(__ICC) && !defined(__CUDACC__) && !defined(__LCC__) #if defined(__GNUC__) && !defined(__clang__) && !defined(__ICC) && !defined(__CUDACC__) && !defined(__LCC__) && !defined(__NVCOMPILER)
# define CATCH_INTERNAL_START_WARNINGS_SUPPRESSION _Pragma( "GCC diagnostic push" ) # define CATCH_INTERNAL_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" )
@@ -60,10 +60,21 @@
#endif #endif
#if defined(__NVCOMPILER)
# define CATCH_INTERNAL_START_WARNINGS_SUPPRESSION _Pragma( "diag push" )
# define CATCH_INTERNAL_STOP_WARNINGS_SUPPRESSION _Pragma( "diag pop" )
# define CATCH_INTERNAL_SUPPRESS_UNUSED_VARIABLE_WARNINGS _Pragma( "diag_suppress declared_but_not_referenced" )
#endif
#if defined(__CUDACC__) && !defined(__clang__) #if defined(__CUDACC__) && !defined(__clang__)
# ifdef __NVCC_DIAG_PRAGMA_SUPPORT__
// New pragmas introduced in CUDA 11.5+
# define CATCH_INTERNAL_START_WARNINGS_SUPPRESSION _Pragma( "nv_diagnostic push" ) # define CATCH_INTERNAL_START_WARNINGS_SUPPRESSION _Pragma( "nv_diagnostic push" )
# define CATCH_INTERNAL_STOP_WARNINGS_SUPPRESSION _Pragma( "nv_diagnostic pop" ) # define CATCH_INTERNAL_STOP_WARNINGS_SUPPRESSION _Pragma( "nv_diagnostic pop" )
# define CATCH_INTERNAL_SUPPRESS_UNUSED_VARIABLE_WARNINGS _Pragma( "nv_diag_suppress 177" ) # define CATCH_INTERNAL_SUPPRESS_UNUSED_VARIABLE_WARNINGS _Pragma( "nv_diag_suppress 177" )
# else
# define CATCH_INTERNAL_SUPPRESS_UNUSED_VARIABLE_WARNINGS _Pragma( "diag_suppress 177" )
# endif
#endif #endif
// clang-cl defines _MSC_VER as well as __clang__, which could cause the // clang-cl defines _MSC_VER as well as __clang__, which could cause the
@@ -181,8 +192,14 @@
// Visual C++ // Visual C++
#if defined(_MSC_VER) #if defined(_MSC_VER)
# define CATCH_INTERNAL_START_WARNINGS_SUPPRESSION __pragma( warning(push) ) // We want to defer to nvcc-specific warning suppression if we are compiled
# define CATCH_INTERNAL_STOP_WARNINGS_SUPPRESSION __pragma( warning(pop) ) // with nvcc masquerading for MSVC.
# if !defined( __CUDACC__ )
# define CATCH_INTERNAL_START_WARNINGS_SUPPRESSION \
__pragma( warning( push ) )
# define CATCH_INTERNAL_STOP_WARNINGS_SUPPRESSION \
__pragma( warning( pop ) )
# 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...)

View File

@@ -47,6 +47,7 @@ namespace Catch {
Error = BrightRed, Error = BrightRed,
Success = Green, Success = Green,
Skip = LightGrey,
OriginalExpression = Cyan, OriginalExpression = Cyan,
ReconstructedExpression = BrightYellow, ReconstructedExpression = BrightYellow,

View File

@@ -19,7 +19,10 @@ namespace Catch {
#if defined(__i386__) || defined(__x86_64__) #if defined(__i386__) || defined(__x86_64__)
#define CATCH_TRAP() __asm__("int $3\n" : : ) /* NOLINT */ #define CATCH_TRAP() __asm__("int $3\n" : : ) /* NOLINT */
#elif defined(__aarch64__) #elif defined(__aarch64__)
#define CATCH_TRAP() __asm__(".inst 0xd43e0000") #define CATCH_TRAP() __asm__(".inst 0xd43e0000")
#elif defined(__POWERPC__)
#define CATCH_TRAP() __asm__("li r0, 20\nsc\nnop\nli r0, 37\nli r4, 2\nsc\nnop\n" \
: : : "memory","r0","r3","r4" ) /* NOLINT */
#endif #endif
#elif defined(CATCH_PLATFORM_IPHONE) #elif defined(CATCH_PLATFORM_IPHONE)

View File

@@ -44,6 +44,9 @@ namespace Catch {
catch( TestFailureException& ) { catch( TestFailureException& ) {
std::rethrow_exception(std::current_exception()); std::rethrow_exception(std::current_exception());
} }
catch( TestSkipException& ) {
std::rethrow_exception(std::current_exception());
}
catch( std::exception const& ex ) { catch( std::exception const& ex ) {
return ex.what(); return ex.what();
} }

View File

@@ -0,0 +1,138 @@
// Copyright Catch2 Authors
// Distributed under the Boost Software License, Version 1.0.
// (See accompanying file LICENSE.txt or copy at
// https://www.boost.org/LICENSE_1_0.txt)
// SPDX-License-Identifier: BSL-1.0
#ifndef CATCH_IS_PERMUTATION_HPP_INCLUDED
#define CATCH_IS_PERMUTATION_HPP_INCLUDED
#include <algorithm>
#include <iterator>
namespace Catch {
namespace Detail {
template <typename ForwardIter,
typename Sentinel,
typename T,
typename Comparator>
ForwardIter find_sentinel( ForwardIter start,
Sentinel sentinel,
T const& value,
Comparator cmp ) {
while ( start != sentinel ) {
if ( cmp( *start, value ) ) { break; }
++start;
}
return start;
}
template <typename ForwardIter,
typename Sentinel,
typename T,
typename Comparator>
std::ptrdiff_t count_sentinel( ForwardIter start,
Sentinel sentinel,
T const& value,
Comparator cmp ) {
std::ptrdiff_t count = 0;
while ( start != sentinel ) {
if ( cmp( *start, value ) ) { ++count; }
++start;
}
return count;
}
template <typename ForwardIter, typename Sentinel>
std::enable_if_t<!std::is_same<ForwardIter, Sentinel>::value,
std::ptrdiff_t>
sentinel_distance( ForwardIter iter, const Sentinel sentinel ) {
std::ptrdiff_t dist = 0;
while ( iter != sentinel ) {
++iter;
++dist;
}
return dist;
}
template <typename ForwardIter>
std::ptrdiff_t sentinel_distance( ForwardIter first,
ForwardIter last ) {
return std::distance( first, last );
}
template <typename ForwardIter1,
typename Sentinel1,
typename ForwardIter2,
typename Sentinel2,
typename Comparator>
bool check_element_counts( ForwardIter1 first_1,
const Sentinel1 end_1,
ForwardIter2 first_2,
const Sentinel2 end_2,
Comparator cmp ) {
auto cursor = first_1;
while ( cursor != end_1 ) {
if ( find_sentinel( first_1, cursor, *cursor, cmp ) ==
cursor ) {
// we haven't checked this element yet
const auto count_in_range_2 =
count_sentinel( first_2, end_2, *cursor, cmp );
// Not a single instance in 2nd range, so it cannot be a
// permutation of 1st range
if ( count_in_range_2 == 0 ) { return false; }
const auto count_in_range_1 =
count_sentinel( cursor, end_1, *cursor, cmp );
if ( count_in_range_1 != count_in_range_2 ) {
return false;
}
}
++cursor;
}
return true;
}
template <typename ForwardIter1,
typename Sentinel1,
typename ForwardIter2,
typename Sentinel2,
typename Comparator>
bool is_permutation( ForwardIter1 first_1,
const Sentinel1 end_1,
ForwardIter2 first_2,
const Sentinel2 end_2,
Comparator cmp ) {
// TODO: no optimization for stronger iterators, because we would also have to constrain on sentinel vs not sentinel types
// TODO: Comparator has to be "both sides", e.g. a == b => b == a
// This skips shared prefix of the two ranges
while (first_1 != end_1 && first_2 != end_2 && cmp(*first_1, *first_2)) {
++first_1;
++first_2;
}
// We need to handle case where at least one of the ranges has no more elements
if (first_1 == end_1 || first_2 == end_2) {
return first_1 == end_1 && first_2 == end_2;
}
// pair counting is n**2, so we pay linear walk to compare the sizes first
auto dist_1 = sentinel_distance( first_1, end_1 );
auto dist_2 = sentinel_distance( first_2, end_2 );
if (dist_1 != dist_2) { return false; }
// Since we do not try to handle stronger iterators pair (e.g.
// bidir) optimally, the only thing left to do is to check counts in
// the remaining ranges.
return check_element_counts( first_1, end_1, first_2, end_2, cmp );
}
} // namespace Detail
} // namespace Catch
#endif // CATCH_IS_PERMUTATION_HPP_INCLUDED

View File

@@ -6,12 +6,12 @@
// SPDX-License-Identifier: BSL-1.0 // SPDX-License-Identifier: BSL-1.0
#include <catch2/internal/catch_parse_numbers.hpp>
#include <catch2/internal/catch_compiler_capabilities.hpp> #include <catch2/internal/catch_compiler_capabilities.hpp>
#include <catch2/internal/catch_parse_numbers.hpp>
#include <catch2/internal/catch_string_manip.hpp> #include <catch2/internal/catch_string_manip.hpp>
#include <limits> #include <limits>
#include <stdexcept>
namespace Catch { namespace Catch {
@@ -39,11 +39,14 @@ namespace Catch {
return {}; return {};
} }
return static_cast<unsigned int>(ret); return static_cast<unsigned int>(ret);
} CATCH_CATCH_ANON( std::exception const& ) {
// There was a larger issue with the input, e.g. the parsed
// number would be too large to fit within ull.
return {};
} }
CATCH_CATCH_ANON( std::invalid_argument const& ) {
// no conversion could be performed
}
CATCH_CATCH_ANON( std::out_of_range const& ) {
// the input does not fit into an unsigned long long
}
return {};
} }
} // namespace Catch } // namespace Catch

View File

@@ -16,6 +16,8 @@ namespace Catch {
Ok = 0, Ok = 0,
Info = 1, Info = 1,
Warning = 2, Warning = 2,
// TODO: Should explicit skip be considered "not OK" (cf. isOk)? I.e., should it have the failure bit?
ExplicitSkip = 4,
FailureBit = 0x10, FailureBit = 0x10,

View File

@@ -29,12 +29,12 @@ namespace Catch {
struct GeneratorTracker : TestCaseTracking::TrackerBase, IGeneratorTracker { struct GeneratorTracker : TestCaseTracking::TrackerBase, IGeneratorTracker {
GeneratorBasePtr m_generator; GeneratorBasePtr m_generator;
GeneratorTracker( TestCaseTracking::NameAndLocation const& nameAndLocation, TrackerContext& ctx, ITracker* parent ) GeneratorTracker( TestCaseTracking::NameAndLocation&& nameAndLocation, TrackerContext& ctx, ITracker* parent )
: TrackerBase( nameAndLocation, ctx, parent ) : TrackerBase( CATCH_MOVE(nameAndLocation), ctx, parent )
{} {}
~GeneratorTracker() override; ~GeneratorTracker() override;
static GeneratorTracker& acquire( TrackerContext& ctx, TestCaseTracking::NameAndLocation const& nameAndLocation ) { static GeneratorTracker* acquire( TrackerContext& ctx, TestCaseTracking::NameAndLocationRef const& nameAndLocation ) {
GeneratorTracker* tracker; GeneratorTracker* tracker;
ITracker& currentTracker = ctx.currentTracker(); ITracker& currentTracker = ctx.currentTracker();
@@ -61,18 +61,14 @@ namespace Catch {
assert( childTracker->isGeneratorTracker() ); assert( childTracker->isGeneratorTracker() );
tracker = static_cast<GeneratorTracker*>( childTracker ); tracker = static_cast<GeneratorTracker*>( childTracker );
} else { } else {
auto newTracker = return nullptr;
Catch::Detail::make_unique<GeneratorTracker>(
nameAndLocation, ctx, &currentTracker );
tracker = newTracker.get();
currentTracker.addChild( CATCH_MOVE(newTracker) );
} }
if( !tracker->isComplete() ) { if( !tracker->isComplete() ) {
tracker->open(); tracker->open();
} }
return *tracker; return tracker;
} }
// TrackerBase interface // TrackerBase interface
@@ -141,6 +137,7 @@ namespace Catch {
// has a side-effect, where it consumes generator's current // has a side-effect, where it consumes generator's current
// value, but we do not want to invoke the side-effect if // value, but we do not want to invoke the side-effect if
// this generator is still waiting for any child to start. // this generator is still waiting for any child to start.
assert( m_generator && "Tracker without generator" );
if ( should_wait_for_child || if ( should_wait_for_child ||
( m_runState == CompletedSuccessfully && ( m_runState == CompletedSuccessfully &&
m_generator->countedNext() ) ) { m_generator->countedNext() ) ) {
@@ -179,13 +176,8 @@ namespace Catch {
Totals RunContext::runTest(TestCaseHandle const& testCase) { Totals RunContext::runTest(TestCaseHandle const& testCase) {
const Totals prevTotals = m_totals; const Totals prevTotals = m_totals;
std::string redirectedCout;
std::string redirectedCerr;
auto const& testInfo = testCase.getTestCaseInfo(); auto const& testInfo = testCase.getTestCaseInfo();
m_reporter->testCaseStarting(testInfo); m_reporter->testCaseStarting(testInfo);
m_activeTestCase = &testCase; m_activeTestCase = &testCase;
@@ -227,9 +219,11 @@ namespace Catch {
seedRng( *m_config ); seedRng( *m_config );
uint64_t testRuns = 0; uint64_t testRuns = 0;
std::string redirectedCout;
std::string redirectedCerr;
do { do {
m_trackerContext.startCycle(); m_trackerContext.startCycle();
m_testCaseTracker = &SectionTracker::acquire(m_trackerContext, TestCaseTracking::NameAndLocation(testInfo.name, testInfo.lineInfo)); m_testCaseTracker = &SectionTracker::acquire(m_trackerContext, TestCaseTracking::NameAndLocationRef(testInfo.name, testInfo.lineInfo));
m_reporter->testCasePartialStarting(testInfo, testRuns); m_reporter->testCasePartialStarting(testInfo, testRuns);
@@ -240,7 +234,7 @@ namespace Catch {
redirectedCerr += oneRunCerr; redirectedCerr += oneRunCerr;
const auto singleRunTotals = m_totals.delta(beforeRunTotals); const auto singleRunTotals = m_totals.delta(beforeRunTotals);
auto statsForOneRun = TestCaseStats(testInfo, singleRunTotals, oneRunCout, oneRunCerr, aborting()); auto statsForOneRun = TestCaseStats(testInfo, singleRunTotals, CATCH_MOVE(oneRunCout), CATCH_MOVE(oneRunCerr), aborting());
m_reporter->testCasePartialEnded(statsForOneRun, testRuns); m_reporter->testCasePartialEnded(statsForOneRun, testRuns);
++testRuns; ++testRuns;
@@ -255,8 +249,8 @@ namespace Catch {
m_totals.testCases += deltaTotals.testCases; m_totals.testCases += deltaTotals.testCases;
m_reporter->testCaseEnded(TestCaseStats(testInfo, m_reporter->testCaseEnded(TestCaseStats(testInfo,
deltaTotals, deltaTotals,
redirectedCout, CATCH_MOVE(redirectedCout),
redirectedCerr, CATCH_MOVE(redirectedCerr),
aborting())); aborting()));
m_activeTestCase = nullptr; m_activeTestCase = nullptr;
@@ -270,6 +264,9 @@ namespace Catch {
if (result.getResultType() == ResultWas::Ok) { if (result.getResultType() == ResultWas::Ok) {
m_totals.assertions.passed++; m_totals.assertions.passed++;
m_lastAssertionPassed = true; m_lastAssertionPassed = true;
} else if (result.getResultType() == ResultWas::ExplicitSkip) {
m_totals.assertions.skipped++;
m_lastAssertionPassed = true;
} else if (!result.succeeded()) { } else if (!result.succeeded()) {
m_lastAssertionPassed = false; m_lastAssertionPassed = false;
if (result.isOk()) { if (result.isOk()) {
@@ -297,12 +294,17 @@ namespace Catch {
m_lastAssertionInfo.capturedExpression = "{Unknown expression after the reported line}"_sr; m_lastAssertionInfo.capturedExpression = "{Unknown expression after the reported line}"_sr;
} }
bool RunContext::sectionStarted(SectionInfo const & sectionInfo, Counts & assertions) { bool RunContext::sectionStarted(StringRef sectionName, SourceLineInfo const& sectionLineInfo, Counts & assertions) {
ITracker& sectionTracker = SectionTracker::acquire(m_trackerContext, TestCaseTracking::NameAndLocation(sectionInfo.name, sectionInfo.lineInfo)); ITracker& sectionTracker =
SectionTracker::acquire( m_trackerContext,
TestCaseTracking::NameAndLocationRef(
sectionName, sectionLineInfo ) );
if (!sectionTracker.isOpen()) if (!sectionTracker.isOpen())
return false; return false;
m_activeSections.push_back(&sectionTracker); m_activeSections.push_back(&sectionTracker);
SectionInfo sectionInfo( sectionLineInfo, static_cast<std::string>(sectionName) );
m_lastAssertionInfo.lineInfo = sectionInfo.lineInfo; m_lastAssertionInfo.lineInfo = sectionInfo.lineInfo;
m_reporter->sectionStarting(sectionInfo); m_reporter->sectionStarting(sectionInfo);
@@ -311,14 +313,39 @@ namespace Catch {
return true; return true;
} }
auto RunContext::acquireGeneratorTracker( StringRef generatorName, SourceLineInfo const& lineInfo ) -> IGeneratorTracker& { IGeneratorTracker*
RunContext::acquireGeneratorTracker( StringRef generatorName,
SourceLineInfo const& lineInfo ) {
using namespace Generators; using namespace Generators;
GeneratorTracker& tracker = GeneratorTracker::acquire(m_trackerContext, GeneratorTracker* tracker = GeneratorTracker::acquire(
TestCaseTracking::NameAndLocation( static_cast<std::string>(generatorName), lineInfo ) ); m_trackerContext,
TestCaseTracking::NameAndLocationRef(
generatorName, lineInfo ) );
m_lastAssertionInfo.lineInfo = lineInfo; m_lastAssertionInfo.lineInfo = lineInfo;
return tracker; return tracker;
} }
IGeneratorTracker* RunContext::createGeneratorTracker(
StringRef generatorName,
SourceLineInfo lineInfo,
Generators::GeneratorBasePtr&& generator ) {
auto nameAndLoc = TestCaseTracking::NameAndLocation( static_cast<std::string>( generatorName ), lineInfo );
auto& currentTracker = m_trackerContext.currentTracker();
assert(
currentTracker.nameAndLocation() != nameAndLoc &&
"Trying to create tracker for a genreator that already has one" );
auto newTracker = Catch::Detail::make_unique<Generators::GeneratorTracker>(
CATCH_MOVE(nameAndLoc), m_trackerContext, &currentTracker );
auto ret = newTracker.get();
currentTracker.addChild( CATCH_MOVE( newTracker ) );
ret->setGenerator( CATCH_MOVE( generator ) );
ret->open();
return ret;
}
bool RunContext::testForMissingAssertions(Counts& assertions) { bool RunContext::testForMissingAssertions(Counts& assertions) {
if (assertions.total() != 0) if (assertions.total() != 0)
return false; return false;
@@ -331,7 +358,7 @@ namespace Catch {
return true; return true;
} }
void RunContext::sectionEnded(SectionEndInfo const & endInfo) { void RunContext::sectionEnded(SectionEndInfo&& endInfo) {
Counts assertions = m_totals.assertions - endInfo.prevAssertions; Counts assertions = m_totals.assertions - endInfo.prevAssertions;
bool missingAssertions = testForMissingAssertions(assertions); bool missingAssertions = testForMissingAssertions(assertions);
@@ -340,19 +367,20 @@ namespace Catch {
m_activeSections.pop_back(); m_activeSections.pop_back();
} }
m_reporter->sectionEnded(SectionStats(endInfo.sectionInfo, assertions, endInfo.durationInSeconds, missingAssertions)); m_reporter->sectionEnded(SectionStats(CATCH_MOVE(endInfo.sectionInfo), assertions, endInfo.durationInSeconds, missingAssertions));
m_messages.clear(); m_messages.clear();
m_messageScopes.clear(); m_messageScopes.clear();
} }
void RunContext::sectionEndedEarly(SectionEndInfo const & endInfo) { void RunContext::sectionEndedEarly(SectionEndInfo&& endInfo) {
if (m_unfinishedSections.empty()) if ( m_unfinishedSections.empty() ) {
m_activeSections.back()->fail(); m_activeSections.back()->fail();
else } else {
m_activeSections.back()->close(); m_activeSections.back()->close();
}
m_activeSections.pop_back(); m_activeSections.pop_back();
m_unfinishedSections.push_back(endInfo); m_unfinishedSections.push_back(CATCH_MOVE(endInfo));
} }
void RunContext::benchmarkPreparing( StringRef name ) { void RunContext::benchmarkPreparing( StringRef name ) {
@@ -376,8 +404,8 @@ namespace Catch {
m_messages.erase(std::remove(m_messages.begin(), m_messages.end(), message), m_messages.end()); m_messages.erase(std::remove(m_messages.begin(), m_messages.end(), message), m_messages.end());
} }
void RunContext::emplaceUnscopedMessage( MessageBuilder const& builder ) { void RunContext::emplaceUnscopedMessage( MessageBuilder&& builder ) {
m_messageScopes.emplace_back( builder ); m_messageScopes.emplace_back( CATCH_MOVE(builder) );
} }
std::string RunContext::getCurrentTestName() const { std::string RunContext::getCurrentTestName() const {
@@ -402,7 +430,7 @@ namespace Catch {
// Instead, fake a result data. // Instead, fake a result data.
AssertionResultData tempResult( ResultWas::FatalErrorCondition, { false } ); AssertionResultData tempResult( ResultWas::FatalErrorCondition, { false } );
tempResult.message = static_cast<std::string>(message); tempResult.message = static_cast<std::string>(message);
AssertionResult result(m_lastAssertionInfo, tempResult); AssertionResult result(m_lastAssertionInfo, CATCH_MOVE(tempResult));
assertionEnded(result); assertionEnded(result);
@@ -414,7 +442,7 @@ namespace Catch {
Counts assertions; Counts assertions;
assertions.failed = 1; assertions.failed = 1;
SectionStats testCaseSectionStats(testCaseSection, assertions, 0, false); SectionStats testCaseSectionStats(CATCH_MOVE(testCaseSection), assertions, 0, false);
m_reporter->sectionEnded(testCaseSectionStats); m_reporter->sectionEnded(testCaseSectionStats);
auto const& testInfo = m_activeTestCase->getTestCaseInfo(); auto const& testInfo = m_activeTestCase->getTestCaseInfo();
@@ -475,6 +503,8 @@ namespace Catch {
duration = timer.getElapsedSeconds(); duration = timer.getElapsedSeconds();
} CATCH_CATCH_ANON (TestFailureException&) { } CATCH_CATCH_ANON (TestFailureException&) {
// This just means the test was aborted due to failure // This just means the test was aborted due to failure
} CATCH_CATCH_ANON (TestSkipException&) {
// This just means the test was explicitly skipped
} CATCH_CATCH_ALL { } CATCH_CATCH_ALL {
// Under CATCH_CONFIG_FAST_COMPILE, unexpected exceptions under REQUIRE assertions // Under CATCH_CONFIG_FAST_COMPILE, unexpected exceptions under REQUIRE assertions
// are reported without translation at the point of origin. // are reported without translation at the point of origin.
@@ -491,7 +521,7 @@ namespace Catch {
m_messages.clear(); m_messages.clear();
m_messageScopes.clear(); m_messageScopes.clear();
SectionStats testCaseSectionStats(testCaseSection, assertions, duration, missingAssertions); SectionStats testCaseSectionStats(CATCH_MOVE(testCaseSection), assertions, duration, missingAssertions);
m_reporter->sectionEnded(testCaseSectionStats); m_reporter->sectionEnded(testCaseSectionStats);
} }
@@ -515,7 +545,7 @@ namespace Catch {
itEnd = m_unfinishedSections.rend(); itEnd = m_unfinishedSections.rend();
it != itEnd; it != itEnd;
++it) ++it)
sectionEnded(*it); sectionEnded(CATCH_MOVE(*it));
m_unfinishedSections.clear(); m_unfinishedSections.clear();
} }
@@ -551,7 +581,7 @@ namespace Catch {
m_lastAssertionInfo = info; m_lastAssertionInfo = info;
AssertionResultData data( resultType, LazyExpression( negated ) ); AssertionResultData data( resultType, LazyExpression( negated ) );
AssertionResult assertionResult{ info, data }; AssertionResult assertionResult{ info, CATCH_MOVE( data ) };
assertionResult.m_resultData.lazyExpression.m_transientExpression = expr; assertionResult.m_resultData.lazyExpression.m_transientExpression = expr;
assertionEnded( assertionResult ); assertionEnded( assertionResult );
@@ -569,10 +599,16 @@ namespace Catch {
AssertionResultData data( resultType, LazyExpression( false ) ); AssertionResultData data( resultType, LazyExpression( false ) );
data.message = static_cast<std::string>(message); data.message = static_cast<std::string>(message);
AssertionResult assertionResult{ m_lastAssertionInfo, data }; AssertionResult assertionResult{ m_lastAssertionInfo,
CATCH_MOVE( data ) };
assertionEnded( assertionResult ); assertionEnded( assertionResult );
if( !assertionResult.isOk() ) if ( !assertionResult.isOk() ) {
populateReaction( reaction ); populateReaction( reaction );
} else if ( resultType == ResultWas::ExplicitSkip ) {
// TODO: Need to handle this explicitly, as ExplicitSkip is
// considered "OK"
reaction.shouldSkip = true;
}
} }
void RunContext::handleUnexpectedExceptionNotThrown( void RunContext::handleUnexpectedExceptionNotThrown(
AssertionInfo const& info, AssertionInfo const& info,
@@ -590,7 +626,7 @@ namespace Catch {
AssertionResultData data( ResultWas::ThrewException, LazyExpression( false ) ); AssertionResultData data( ResultWas::ThrewException, LazyExpression( false ) );
data.message = message; data.message = message;
AssertionResult assertionResult{ info, data }; AssertionResult assertionResult{ info, CATCH_MOVE(data) };
assertionEnded( assertionResult ); assertionEnded( assertionResult );
populateReaction( reaction ); populateReaction( reaction );
} }
@@ -603,11 +639,12 @@ namespace Catch {
void RunContext::handleIncomplete( void RunContext::handleIncomplete(
AssertionInfo const& info AssertionInfo const& info
) { ) {
using namespace std::string_literals;
m_lastAssertionInfo = info; m_lastAssertionInfo = info;
AssertionResultData data( ResultWas::ThrewException, LazyExpression( false ) ); AssertionResultData data( ResultWas::ThrewException, LazyExpression( false ) );
data.message = "Exception translation was disabled by CATCH_CONFIG_FAST_COMPILE"; data.message = "Exception translation was disabled by CATCH_CONFIG_FAST_COMPILE"s;
AssertionResult assertionResult{ info, data }; AssertionResult assertionResult{ info, CATCH_MOVE( data ) };
assertionEnded( assertionResult ); assertionEnded( assertionResult );
} }
void RunContext::handleNonExpr( void RunContext::handleNonExpr(
@@ -618,7 +655,7 @@ namespace Catch {
m_lastAssertionInfo = info; m_lastAssertionInfo = info;
AssertionResultData data( resultType, LazyExpression( false ) ); AssertionResultData data( resultType, LazyExpression( false ) );
AssertionResult assertionResult{ info, data }; AssertionResult assertionResult{ info, CATCH_MOVE( data ) };
assertionEnded( assertionResult ); assertionEnded( assertionResult );
if( !assertionResult.isOk() ) if( !assertionResult.isOk() )

View File

@@ -68,12 +68,21 @@ namespace Catch {
ResultWas::OfType resultType, ResultWas::OfType resultType,
AssertionReaction &reaction ) override; AssertionReaction &reaction ) override;
bool sectionStarted( SectionInfo const& sectionInfo, Counts& assertions ) override; bool sectionStarted( StringRef sectionName,
SourceLineInfo const& sectionLineInfo,
Counts& assertions ) override;
void sectionEnded( SectionEndInfo const& endInfo ) override; void sectionEnded( SectionEndInfo&& endInfo ) override;
void sectionEndedEarly( SectionEndInfo const& endInfo ) override; void sectionEndedEarly( SectionEndInfo&& endInfo ) override;
IGeneratorTracker*
acquireGeneratorTracker( StringRef generatorName,
SourceLineInfo const& lineInfo ) override;
IGeneratorTracker* createGeneratorTracker(
StringRef generatorName,
SourceLineInfo lineInfo,
Generators::GeneratorBasePtr&& generator ) override;
auto acquireGeneratorTracker( StringRef generatorName, SourceLineInfo const& lineInfo ) -> IGeneratorTracker& override;
void benchmarkPreparing( StringRef name ) override; void benchmarkPreparing( StringRef name ) override;
void benchmarkStarting( BenchmarkInfo const& info ) override; void benchmarkStarting( BenchmarkInfo const& info ) override;
@@ -83,7 +92,7 @@ namespace Catch {
void pushScopedMessage( MessageInfo const& message ) override; void pushScopedMessage( MessageInfo const& message ) override;
void popScopedMessage( MessageInfo const& message ) override; void popScopedMessage( MessageInfo const& message ) override;
void emplaceUnscopedMessage( MessageBuilder const& builder ) override; void emplaceUnscopedMessage( MessageBuilder&& builder ) override;
std::string getCurrentTestName() const override; std::string getCurrentTestName() const override;

View File

@@ -15,7 +15,7 @@ namespace Catch {
Section::Section( SectionInfo&& info ): Section::Section( SectionInfo&& info ):
m_info( CATCH_MOVE( info ) ), m_info( CATCH_MOVE( info ) ),
m_sectionIncluded( m_sectionIncluded(
getResultCapture().sectionStarted( m_info, m_assertions ) ) { getResultCapture().sectionStarted( m_info.name, m_info.lineInfo, m_assertions ) ) {
// Non-"included" sections will not use the timing information // Non-"included" sections will not use the timing information
// anyway, so don't bother with the potential syscall. // anyway, so don't bother with the potential syscall.
if (m_sectionIncluded) { if (m_sectionIncluded) {
@@ -23,13 +23,31 @@ namespace Catch {
} }
} }
Section::Section( SourceLineInfo const& _lineInfo,
StringRef _name,
const char* const ):
m_info( { "invalid", static_cast<std::size_t>( -1 ) }, std::string{} ),
m_sectionIncluded(
getResultCapture().sectionStarted( _name, _lineInfo, m_assertions ) ) {
// We delay initialization the SectionInfo member until we know
// this section needs it, so we avoid allocating std::string for name.
// We also delay timer start to avoid the potential syscall unless we
// will actually use the result.
if ( m_sectionIncluded ) {
m_info.name = static_cast<std::string>( _name );
m_info.lineInfo = _lineInfo;
m_timer.start();
}
}
Section::~Section() { Section::~Section() {
if( m_sectionIncluded ) { if( m_sectionIncluded ) {
SectionEndInfo endInfo{ m_info, m_assertions, m_timer.getElapsedSeconds() }; SectionEndInfo endInfo{ CATCH_MOVE(m_info), m_assertions, m_timer.getElapsedSeconds() };
if( uncaught_exceptions() ) if ( uncaught_exceptions() ) {
getResultCapture().sectionEndedEarly( endInfo ); getResultCapture().sectionEndedEarly( CATCH_MOVE(endInfo) );
else } else {
getResultCapture().sectionEnded( endInfo ); getResultCapture().sectionEnded( CATCH_MOVE( endInfo ) );
}
} }
} }

View File

@@ -20,6 +20,9 @@ namespace Catch {
class Section : Detail::NonCopyable { class Section : Detail::NonCopyable {
public: public:
Section( SectionInfo&& info ); Section( SectionInfo&& info );
Section( SourceLineInfo const& _lineInfo,
StringRef _name,
const char* const = nullptr );
~Section(); ~Section();
// This indicates whether the section should be executed or not // This indicates whether the section should be executed or not
@@ -38,7 +41,7 @@ namespace Catch {
#define INTERNAL_CATCH_SECTION( ... ) \ #define INTERNAL_CATCH_SECTION( ... ) \
CATCH_INTERNAL_START_WARNINGS_SUPPRESSION \ CATCH_INTERNAL_START_WARNINGS_SUPPRESSION \
CATCH_INTERNAL_SUPPRESS_UNUSED_VARIABLE_WARNINGS \ CATCH_INTERNAL_SUPPRESS_UNUSED_VARIABLE_WARNINGS \
if( Catch::Section const& INTERNAL_CATCH_UNIQUE_NAME( catch_internal_Section ) = Catch::SectionInfo( CATCH_INTERNAL_LINEINFO, __VA_ARGS__ ) ) \ if( Catch::Section const& INTERNAL_CATCH_UNIQUE_NAME( catch_internal_Section ) = Catch::Section( CATCH_INTERNAL_LINEINFO, __VA_ARGS__ ) ) \
CATCH_INTERNAL_STOP_WARNINGS_SUPPRESSION CATCH_INTERNAL_STOP_WARNINGS_SUPPRESSION
#define INTERNAL_CATCH_DYNAMIC_SECTION( ... ) \ #define INTERNAL_CATCH_DYNAMIC_SECTION( ... ) \

View File

@@ -10,6 +10,7 @@
#include <catch2/internal/catch_stringref.hpp> #include <catch2/internal/catch_stringref.hpp>
#include <cstdint>
#include <string> #include <string>
#include <iosfwd> #include <iosfwd>
#include <vector> #include <vector>

View File

@@ -17,10 +17,6 @@ namespace Catch {
: StringRef( rawChars, std::strlen(rawChars) ) : StringRef( rawChars, std::strlen(rawChars) )
{} {}
auto StringRef::operator == ( StringRef other ) const noexcept -> bool {
return m_size == other.m_size
&& (std::memcmp( m_start, other.m_start, m_size ) == 0);
}
bool StringRef::operator<(StringRef rhs) const noexcept { bool StringRef::operator<(StringRef rhs) const noexcept {
if (m_size < rhs.m_size) { if (m_size < rhs.m_size) {

View File

@@ -13,6 +13,8 @@
#include <iosfwd> #include <iosfwd>
#include <cassert> #include <cassert>
#include <cstring>
namespace Catch { namespace Catch {
/// A non-owning string class (similar to the forthcoming std::string_view) /// A non-owning string class (similar to the forthcoming std::string_view)
@@ -49,7 +51,10 @@ namespace Catch {
} }
public: // operators public: // operators
auto operator == ( StringRef other ) const noexcept -> bool; auto operator == ( StringRef other ) const noexcept -> bool {
return m_size == other.m_size
&& (std::memcmp( m_start, other.m_start, m_size ) == 0);
}
auto operator != (StringRef other) const noexcept -> bool { auto operator != (StringRef other) const noexcept -> bool {
return !(*this == other); return !(*this == other);
} }

View File

@@ -181,7 +181,7 @@
void reg_tests() { \ void reg_tests() { \
size_t index = 0; \ size_t index = 0; \
using expander = size_t[]; \ using expander = size_t[]; \
(void)expander{(Catch::AutoReg( Catch::makeTestInvoker( &TestFunc<Types> ), CATCH_INTERNAL_LINEINFO, Catch::StringRef(), Catch::NameAndTags{ Name " - " + std::string(INTERNAL_CATCH_STRINGIZE(TmplList)) + " - " + std::to_string(index), Tags } ), index++)... };/* NOLINT */\ (void)expander{(Catch::AutoReg( Catch::makeTestInvoker( &TestFunc<Types> ), CATCH_INTERNAL_LINEINFO, Catch::StringRef(), Catch::NameAndTags{ Name " - " INTERNAL_CATCH_STRINGIZE(TmplList) " - " + std::to_string(index), Tags } ), index++)... };/* NOLINT */\
} \ } \
};\ };\
static int INTERNAL_CATCH_UNIQUE_NAME( globalRegistrar ) = [](){ \ static int INTERNAL_CATCH_UNIQUE_NAME( globalRegistrar ) = [](){ \
@@ -316,7 +316,7 @@
void reg_tests(){\ void reg_tests(){\
size_t index = 0;\ size_t index = 0;\
using expander = size_t[];\ using expander = size_t[];\
(void)expander{(Catch::AutoReg( Catch::makeTestInvoker( &TestName<Types>::test ), CATCH_INTERNAL_LINEINFO, #ClassName, Catch::NameAndTags{ Name " - " + std::string(INTERNAL_CATCH_STRINGIZE(TmplList)) + " - " + std::to_string(index), Tags } ), index++)... };/* NOLINT */ \ (void)expander{(Catch::AutoReg( Catch::makeTestInvoker( &TestName<Types>::test ), CATCH_INTERNAL_LINEINFO, #ClassName##_catch_sr, Catch::NameAndTags{ Name " - " INTERNAL_CATCH_STRINGIZE(TmplList) " - " + std::to_string(index), Tags } ), index++)... };/* NOLINT */ \
}\ }\
};\ };\
static int INTERNAL_CATCH_UNIQUE_NAME( globalRegistrar ) = [](){\ static int INTERNAL_CATCH_UNIQUE_NAME( globalRegistrar ) = [](){\

View File

@@ -22,8 +22,8 @@
namespace Catch { namespace Catch {
namespace TestCaseTracking { namespace TestCaseTracking {
NameAndLocation::NameAndLocation( std::string const& _name, SourceLineInfo const& _location ) NameAndLocation::NameAndLocation( std::string&& _name, SourceLineInfo const& _location )
: name( _name ), : name( CATCH_MOVE(_name) ),
location( _location ) location( _location )
{} {}
@@ -38,14 +38,17 @@ namespace TestCaseTracking {
m_children.push_back( CATCH_MOVE(child) ); m_children.push_back( CATCH_MOVE(child) );
} }
ITracker* ITracker::findChild( NameAndLocation const& nameAndLocation ) { ITracker* ITracker::findChild( NameAndLocationRef const& nameAndLocation ) {
auto it = std::find_if( auto it = std::find_if(
m_children.begin(), m_children.begin(),
m_children.end(), m_children.end(),
[&nameAndLocation]( ITrackerPtr const& tracker ) { [&nameAndLocation]( ITrackerPtr const& tracker ) {
return tracker->nameAndLocation().location == auto const& tnameAndLoc = tracker->nameAndLocation();
nameAndLocation.location && if ( tnameAndLoc.location.line !=
tracker->nameAndLocation().name == nameAndLocation.name; nameAndLocation.location.line ) {
return false;
}
return tnameAndLoc == nameAndLocation;
} ); } );
return ( it != m_children.end() ) ? it->get() : nullptr; return ( it != m_children.end() ) ? it->get() : nullptr;
} }
@@ -53,10 +56,6 @@ namespace TestCaseTracking {
bool ITracker::isSectionTracker() const { return false; } bool ITracker::isSectionTracker() const { return false; }
bool ITracker::isGeneratorTracker() const { return false; } bool ITracker::isGeneratorTracker() const { return false; }
bool ITracker::isSuccessfullyCompleted() const {
return m_runState == CompletedSuccessfully;
}
bool ITracker::isOpen() const { bool ITracker::isOpen() const {
return m_runState != NotStarted && !isComplete(); return m_runState != NotStarted && !isComplete();
} }
@@ -83,16 +82,6 @@ namespace TestCaseTracking {
return *m_rootTracker; return *m_rootTracker;
} }
void TrackerContext::endRun() {
m_rootTracker.reset();
m_currentTracker = nullptr;
m_runState = NotStarted;
}
void TrackerContext::startCycle() {
m_currentTracker = m_rootTracker.get();
m_runState = Executing;
}
void TrackerContext::completeCycle() { void TrackerContext::completeCycle() {
m_runState = CompletedCycle; m_runState = CompletedCycle;
} }
@@ -100,16 +89,13 @@ namespace TestCaseTracking {
bool TrackerContext::completedCycle() const { bool TrackerContext::completedCycle() const {
return m_runState == CompletedCycle; return m_runState == CompletedCycle;
} }
ITracker& TrackerContext::currentTracker() {
return *m_currentTracker;
}
void TrackerContext::setCurrentTracker( ITracker* tracker ) { void TrackerContext::setCurrentTracker( ITracker* tracker ) {
m_currentTracker = tracker; m_currentTracker = tracker;
} }
TrackerBase::TrackerBase( NameAndLocation const& nameAndLocation, TrackerContext& ctx, ITracker* parent ): TrackerBase::TrackerBase( NameAndLocation&& nameAndLocation, TrackerContext& ctx, ITracker* parent ):
ITracker(nameAndLocation, parent), ITracker(CATCH_MOVE(nameAndLocation), parent),
m_ctx( ctx ) m_ctx( ctx )
{} {}
@@ -169,13 +155,14 @@ namespace TestCaseTracking {
m_ctx.setCurrentTracker( this ); m_ctx.setCurrentTracker( this );
} }
SectionTracker::SectionTracker( NameAndLocation const& nameAndLocation, TrackerContext& ctx, ITracker* parent ) SectionTracker::SectionTracker( NameAndLocation&& nameAndLocation, TrackerContext& ctx, ITracker* parent )
: TrackerBase( nameAndLocation, ctx, parent ), : TrackerBase( CATCH_MOVE(nameAndLocation), ctx, parent ),
m_trimmed_name(trim(nameAndLocation.name)) m_trimmed_name(trim(StringRef(ITracker::nameAndLocation().name)))
{ {
if( parent ) { if( parent ) {
while( !parent->isSectionTracker() ) while ( !parent->isSectionTracker() ) {
parent = parent->parent(); parent = parent->parent();
}
SectionTracker& parentSection = static_cast<SectionTracker&>( *parent ); SectionTracker& parentSection = static_cast<SectionTracker&>( *parent );
addNextFilters( parentSection.m_filters ); addNextFilters( parentSection.m_filters );
@@ -195,24 +182,30 @@ namespace TestCaseTracking {
bool SectionTracker::isSectionTracker() const { return true; } bool SectionTracker::isSectionTracker() const { return true; }
SectionTracker& SectionTracker::acquire( TrackerContext& ctx, NameAndLocation const& nameAndLocation ) { SectionTracker& SectionTracker::acquire( TrackerContext& ctx, NameAndLocationRef const& nameAndLocation ) {
SectionTracker* section; SectionTracker* tracker;
ITracker& currentTracker = ctx.currentTracker(); ITracker& currentTracker = ctx.currentTracker();
if ( ITracker* childTracker = if ( ITracker* childTracker =
currentTracker.findChild( nameAndLocation ) ) { currentTracker.findChild( nameAndLocation ) ) {
assert( childTracker ); assert( childTracker );
assert( childTracker->isSectionTracker() ); assert( childTracker->isSectionTracker() );
section = static_cast<SectionTracker*>( childTracker ); tracker = static_cast<SectionTracker*>( childTracker );
} else { } else {
auto newSection = Catch::Detail::make_unique<SectionTracker>( auto newTracker = Catch::Detail::make_unique<SectionTracker>(
nameAndLocation, ctx, &currentTracker ); NameAndLocation{ static_cast<std::string>(nameAndLocation.name),
section = newSection.get(); nameAndLocation.location },
currentTracker.addChild( CATCH_MOVE( newSection ) ); ctx,
&currentTracker );
tracker = newTracker.get();
currentTracker.addChild( CATCH_MOVE( newTracker ) );
} }
if( !ctx.completedCycle() )
section->tryOpen(); if ( !ctx.completedCycle() ) {
return *section; tracker->tryOpen();
}
return *tracker;
} }
void SectionTracker::tryOpen() { void SectionTracker::tryOpen() {
@@ -233,10 +226,6 @@ 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<StringRef> const& SectionTracker::getFilters() const {
return m_filters;
}
StringRef SectionTracker::trimmedName() const { StringRef SectionTracker::trimmedName() const {
return m_trimmed_name; return m_trimmed_name;
} }

View File

@@ -22,10 +22,49 @@ namespace TestCaseTracking {
std::string name; std::string name;
SourceLineInfo location; SourceLineInfo location;
NameAndLocation( std::string const& _name, SourceLineInfo const& _location ); NameAndLocation( std::string&& _name, SourceLineInfo const& _location );
friend bool operator==(NameAndLocation const& lhs, NameAndLocation const& rhs) { friend bool operator==(NameAndLocation const& lhs, NameAndLocation const& rhs) {
return lhs.name == rhs.name // This is a very cheap check that should have a very high hit rate.
&& lhs.location == rhs.location; // If we get to SourceLineInfo::operator==, we will redo it, but the
// cost of repeating is trivial at that point (we will be paying
// multiple strcmp/memcmps at that point).
if ( lhs.location.line != rhs.location.line ) { return false; }
return lhs.name == rhs.name && lhs.location == rhs.location;
}
friend bool operator!=(NameAndLocation const& lhs,
NameAndLocation const& rhs) {
return !( lhs == rhs );
}
};
/**
* This is a variant of `NameAndLocation` that does not own the name string
*
* This avoids extra allocations when trying to locate a tracker by its
* name and location, as long as we make sure that trackers only keep
* around the owning variant.
*/
struct NameAndLocationRef {
StringRef name;
SourceLineInfo location;
constexpr NameAndLocationRef( StringRef name_,
SourceLineInfo location_ ):
name( name_ ), location( location_ ) {}
friend bool operator==( NameAndLocation const& lhs,
NameAndLocationRef const& rhs ) {
// This is a very cheap check that should have a very high hit rate.
// If we get to SourceLineInfo::operator==, we will redo it, but the
// cost of repeating is trivial at that point (we will be paying
// multiple strcmp/memcmps at that point).
if ( lhs.location.line != rhs.location.line ) { return false; }
return StringRef( lhs.name ) == rhs.name &&
lhs.location == rhs.location;
}
friend bool operator==( NameAndLocationRef const& lhs,
NameAndLocation const& rhs ) {
return rhs == lhs;
} }
}; };
@@ -53,8 +92,8 @@ namespace TestCaseTracking {
CycleState m_runState = NotStarted; CycleState m_runState = NotStarted;
public: public:
ITracker( NameAndLocation const& nameAndLoc, ITracker* parent ): ITracker( NameAndLocation&& nameAndLoc, ITracker* parent ):
m_nameAndLocation( nameAndLoc ), m_nameAndLocation( CATCH_MOVE(nameAndLoc) ),
m_parent( parent ) m_parent( parent )
{} {}
@@ -75,7 +114,9 @@ namespace TestCaseTracking {
//! Returns true if tracker run to completion (successfully or not) //! Returns true if tracker run to completion (successfully or not)
virtual bool isComplete() const = 0; virtual bool isComplete() const = 0;
//! Returns true if tracker run to completion succesfully //! Returns true if tracker run to completion succesfully
bool isSuccessfullyCompleted() const; bool isSuccessfullyCompleted() const {
return m_runState == CompletedSuccessfully;
}
//! Returns true if tracker has started but hasn't been completed //! Returns true if tracker has started but hasn't been completed
bool isOpen() const; bool isOpen() const;
//! Returns true iff tracker has started //! Returns true iff tracker has started
@@ -93,7 +134,7 @@ namespace TestCaseTracking {
* *
* Returns nullptr if not found. * Returns nullptr if not found.
*/ */
ITracker* findChild( NameAndLocation const& nameAndLocation ); ITracker* findChild( NameAndLocationRef const& nameAndLocation );
//! Have any children been added? //! Have any children been added?
bool hasChildren() const { bool hasChildren() const {
return !m_children.empty(); return !m_children.empty();
@@ -134,13 +175,15 @@ namespace TestCaseTracking {
public: public:
ITracker& startRun(); ITracker& startRun();
void endRun();
void startCycle(); void startCycle() {
m_currentTracker = m_rootTracker.get();
m_runState = Executing;
}
void completeCycle(); void completeCycle();
bool completedCycle() const; bool completedCycle() const;
ITracker& currentTracker(); ITracker& currentTracker() { return *m_currentTracker; }
void setCurrentTracker( ITracker* tracker ); void setCurrentTracker( ITracker* tracker );
}; };
@@ -150,7 +193,7 @@ namespace TestCaseTracking {
TrackerContext& m_ctx; TrackerContext& m_ctx;
public: public:
TrackerBase( NameAndLocation const& nameAndLocation, TrackerContext& ctx, ITracker* parent ); TrackerBase( NameAndLocation&& nameAndLocation, TrackerContext& ctx, ITracker* parent );
bool isComplete() const override; bool isComplete() const override;
@@ -166,22 +209,26 @@ namespace TestCaseTracking {
class SectionTracker : public TrackerBase { class SectionTracker : public TrackerBase {
std::vector<StringRef> m_filters; std::vector<StringRef> m_filters;
std::string m_trimmed_name; // Note that lifetime-wise we piggy back off the name stored in the `ITracker` parent`.
// Currently it allocates owns the name, so this is safe. If it is later refactored
// to not own the name, the name still has to outlive the `ITracker` parent, so
// this should still be safe.
StringRef m_trimmed_name;
public: public:
SectionTracker( NameAndLocation const& nameAndLocation, TrackerContext& ctx, ITracker* parent ); SectionTracker( NameAndLocation&& nameAndLocation, TrackerContext& ctx, ITracker* parent );
bool isSectionTracker() const override; bool isSectionTracker() const override;
bool isComplete() const override; bool isComplete() const override;
static SectionTracker& acquire( TrackerContext& ctx, NameAndLocation const& nameAndLocation ); static SectionTracker& acquire( TrackerContext& ctx, NameAndLocationRef const& nameAndLocation );
void tryOpen(); void tryOpen();
void addInitialFilters( std::vector<std::string> const& filters ); void addInitialFilters( std::vector<std::string> const& filters );
void addNextFilters( std::vector<StringRef> const& filters ); void addNextFilters( std::vector<StringRef> const& filters );
//! Returns filters active in this tracker //! Returns filters active in this tracker
std::vector<StringRef> const& getFilters() const; std::vector<StringRef> const& getFilters() const { return m_filters; }
//! Returns whitespace-trimmed name of the tracked section //! Returns whitespace-trimmed name of the tracked section
StringRef trimmedName() const; StringRef trimmedName() const;
}; };

View File

@@ -20,6 +20,9 @@ namespace Catch {
*/ */
[[noreturn]] void throw_test_failure_exception(); [[noreturn]] void throw_test_failure_exception();
//! Used to signal that the remainder of a test should be skipped
struct TestSkipException{};
} // namespace Catch } // namespace Catch
#endif // CATCH_TEST_FAILURE_EXCEPTION_HPP_INCLUDED #endif // CATCH_TEST_FAILURE_EXCEPTION_HPP_INCLUDED

View File

@@ -23,9 +23,9 @@
#if !defined(CATCH_CONFIG_DISABLE) #if !defined(CATCH_CONFIG_DISABLE)
#if !defined(CATCH_CONFIG_DISABLE_STRINGIFICATION) #if !defined(CATCH_CONFIG_DISABLE_STRINGIFICATION)
#define CATCH_INTERNAL_STRINGIFY(...) #__VA_ARGS__ #define CATCH_INTERNAL_STRINGIFY(...) #__VA_ARGS__##_catch_sr
#else #else
#define CATCH_INTERNAL_STRINGIFY(...) "Disabled by CATCH_CONFIG_DISABLE_STRINGIFICATION" #define CATCH_INTERNAL_STRINGIFY(...) "Disabled by CATCH_CONFIG_DISABLE_STRINGIFICATION"_catch_sr
#endif #endif
#if defined(CATCH_CONFIG_FAST_COMPILE) || defined(CATCH_CONFIG_DISABLE_EXCEPTIONS) #if defined(CATCH_CONFIG_FAST_COMPILE) || defined(CATCH_CONFIG_DISABLE_EXCEPTIONS)

View File

@@ -78,7 +78,7 @@ struct AutoReg : Detail::NonCopyable {
CATCH_INTERNAL_START_WARNINGS_SUPPRESSION \ CATCH_INTERNAL_START_WARNINGS_SUPPRESSION \
CATCH_INTERNAL_SUPPRESS_GLOBALS_WARNINGS \ CATCH_INTERNAL_SUPPRESS_GLOBALS_WARNINGS \
CATCH_INTERNAL_SUPPRESS_UNUSED_VARIABLE_WARNINGS \ CATCH_INTERNAL_SUPPRESS_UNUSED_VARIABLE_WARNINGS \
namespace{ Catch::AutoReg INTERNAL_CATCH_UNIQUE_NAME( autoRegistrar )( Catch::makeTestInvoker( &TestName ), CATCH_INTERNAL_LINEINFO, Catch::StringRef(), Catch::NameAndTags{ __VA_ARGS__ } ); } /* NOLINT */ \ namespace{ const Catch::AutoReg INTERNAL_CATCH_UNIQUE_NAME( autoRegistrar )( Catch::makeTestInvoker( &TestName ), CATCH_INTERNAL_LINEINFO, Catch::StringRef(), Catch::NameAndTags{ __VA_ARGS__ } ); } /* NOLINT */ \
CATCH_INTERNAL_STOP_WARNINGS_SUPPRESSION \ CATCH_INTERNAL_STOP_WARNINGS_SUPPRESSION \
static void TestName() static void TestName()
#define INTERNAL_CATCH_TESTCASE( ... ) \ #define INTERNAL_CATCH_TESTCASE( ... ) \
@@ -89,7 +89,13 @@ struct AutoReg : Detail::NonCopyable {
CATCH_INTERNAL_START_WARNINGS_SUPPRESSION \ CATCH_INTERNAL_START_WARNINGS_SUPPRESSION \
CATCH_INTERNAL_SUPPRESS_GLOBALS_WARNINGS \ CATCH_INTERNAL_SUPPRESS_GLOBALS_WARNINGS \
CATCH_INTERNAL_SUPPRESS_UNUSED_VARIABLE_WARNINGS \ CATCH_INTERNAL_SUPPRESS_UNUSED_VARIABLE_WARNINGS \
namespace{ Catch::AutoReg INTERNAL_CATCH_UNIQUE_NAME( autoRegistrar )( Catch::makeTestInvoker( &QualifiedMethod ), CATCH_INTERNAL_LINEINFO, "&" #QualifiedMethod, Catch::NameAndTags{ __VA_ARGS__ } ); } /* NOLINT */ \ namespace { \
const Catch::AutoReg INTERNAL_CATCH_UNIQUE_NAME( autoRegistrar )( \
Catch::makeTestInvoker( &QualifiedMethod ), \
CATCH_INTERNAL_LINEINFO, \
"&" #QualifiedMethod##_catch_sr, \
Catch::NameAndTags{ __VA_ARGS__ } ); \
} /* NOLINT */ \
CATCH_INTERNAL_STOP_WARNINGS_SUPPRESSION CATCH_INTERNAL_STOP_WARNINGS_SUPPRESSION
/////////////////////////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////////////////////////
@@ -101,7 +107,11 @@ struct AutoReg : Detail::NonCopyable {
struct TestName : INTERNAL_CATCH_REMOVE_PARENS(ClassName) { \ struct TestName : INTERNAL_CATCH_REMOVE_PARENS(ClassName) { \
void test(); \ void test(); \
}; \ }; \
Catch::AutoReg INTERNAL_CATCH_UNIQUE_NAME( autoRegistrar ) ( Catch::makeTestInvoker( &TestName::test ), CATCH_INTERNAL_LINEINFO, #ClassName, Catch::NameAndTags{ __VA_ARGS__ } ); /* NOLINT */ \ const Catch::AutoReg INTERNAL_CATCH_UNIQUE_NAME( autoRegistrar )( \
Catch::makeTestInvoker( &TestName::test ), \
CATCH_INTERNAL_LINEINFO, \
#ClassName##_catch_sr, \
Catch::NameAndTags{ __VA_ARGS__ } ); /* NOLINT */ \
} \ } \
CATCH_INTERNAL_STOP_WARNINGS_SUPPRESSION \ CATCH_INTERNAL_STOP_WARNINGS_SUPPRESSION \
void TestName::test() void TestName::test()

View File

@@ -221,10 +221,8 @@ namespace Catch {
token.erase(token.begin()); token.erase(token.begin());
if (m_exclusion) { if (m_exclusion) {
m_currentFilter.m_forbidden.emplace_back(Detail::make_unique<TestSpec::TagPattern>(".", m_substring)); m_currentFilter.m_forbidden.emplace_back(Detail::make_unique<TestSpec::TagPattern>(".", m_substring));
m_currentFilter.m_forbidden.emplace_back(Detail::make_unique<TestSpec::TagPattern>(token, m_substring));
} else { } else {
m_currentFilter.m_required.emplace_back(Detail::make_unique<TestSpec::TagPattern>(".", m_substring)); m_currentFilter.m_required.emplace_back(Detail::make_unique<TestSpec::TagPattern>(".", m_substring));
m_currentFilter.m_required.emplace_back(Detail::make_unique<TestSpec::TagPattern>(token, m_substring));
} }
} }
if (m_exclusion) { if (m_exclusion) {

View File

@@ -11,6 +11,7 @@
#include <catch2/internal/catch_enforce.hpp> #include <catch2/internal/catch_enforce.hpp>
#include <catch2/internal/catch_xmlwriter.hpp> #include <catch2/internal/catch_xmlwriter.hpp>
#include <cstdint>
#include <iomanip> #include <iomanip>
#include <type_traits> #include <type_traits>

View File

@@ -27,6 +27,7 @@
#include <catch2/matchers/catch_matchers_floating_point.hpp> #include <catch2/matchers/catch_matchers_floating_point.hpp>
#include <catch2/matchers/catch_matchers_predicate.hpp> #include <catch2/matchers/catch_matchers_predicate.hpp>
#include <catch2/matchers/catch_matchers_quantifiers.hpp> #include <catch2/matchers/catch_matchers_quantifiers.hpp>
#include <catch2/matchers/catch_matchers_range_equals.hpp>
#include <catch2/matchers/catch_matchers_string.hpp> #include <catch2/matchers/catch_matchers_string.hpp>
#include <catch2/matchers/catch_matchers_templated.hpp> #include <catch2/matchers/catch_matchers_templated.hpp>
#include <catch2/matchers/catch_matchers_vector.hpp> #include <catch2/matchers/catch_matchers_vector.hpp>

View File

@@ -33,13 +33,11 @@ namespace Catch {
} }
template <typename RangeLike> template <typename RangeLike>
bool match(RangeLike&& rng) const { bool match( RangeLike&& rng ) const {
using std::begin; using std::end; for ( auto&& elem : rng ) {
if ( m_eq( elem, m_desired ) ) { return true; }
return end(rng) != std::find_if(begin(rng), end(rng), }
[&](auto const& elem) { return false;
return m_eq(elem, m_desired);
});
} }
}; };
@@ -91,7 +89,7 @@ namespace Catch {
/** /**
* Creates a matcher that checks whether a range contains a specific element. * Creates a matcher that checks whether a range contains a specific element.
* *
* Uses `eq` to do the comparisons * Uses `eq` to do the comparisons, the element is provided on the rhs
*/ */
template <typename T, typename Equality> template <typename T, typename Equality>
ContainsElementMatcher<T, Equality> Contains(T&& elem, Equality&& eq) { ContainsElementMatcher<T, Equality> Contains(T&& elem, Equality&& eq) {

View File

@@ -29,6 +29,32 @@ public:
//! Creates a matcher that checks whether a std derived exception has the provided message //! Creates a matcher that checks whether a std derived exception has the provided message
ExceptionMessageMatcher Message(std::string const& message); ExceptionMessageMatcher Message(std::string const& message);
template <typename StringMatcherType>
class ExceptionMessageMatchesMatcher final
: public MatcherBase<std::exception> {
StringMatcherType m_matcher;
public:
ExceptionMessageMatchesMatcher( StringMatcherType matcher ):
m_matcher( CATCH_MOVE( matcher ) ) {}
bool match( std::exception const& ex ) const override {
return m_matcher.match( ex.what() );
}
std::string describe() const override {
return " matches \"" + m_matcher.describe() + '"';
}
};
//! Creates a matcher that checks whether a message from an std derived
//! exception matches a provided matcher
template <typename StringMatcherType>
ExceptionMessageMatchesMatcher<StringMatcherType>
MessageMatches( StringMatcherType&& matcher ) {
return { CATCH_FORWARD( matcher ) };
}
} // namespace Matchers } // namespace Matchers
} // namespace Catch } // namespace Catch

View File

@@ -225,5 +225,17 @@ WithinRelMatcher WithinRel(float target) {
} }
} // namespace Matchers
bool IsNaNMatcher::match( double const& matchee ) const {
return std::isnan( matchee );
}
std::string IsNaNMatcher::describe() const {
using namespace std::string_literals;
return "is NaN"s;
}
IsNaNMatcher IsNaN() { return IsNaNMatcher(); }
} // namespace Matchers
} // namespace Catch } // namespace Catch

View File

@@ -27,6 +27,11 @@ namespace Matchers {
double m_margin; double m_margin;
}; };
//! Creates a matcher that accepts numbers within certain range of target
WithinAbsMatcher WithinAbs( double target, double margin );
class WithinUlpsMatcher final : public MatcherBase<double> { class WithinUlpsMatcher final : public MatcherBase<double> {
public: public:
WithinUlpsMatcher( double target, WithinUlpsMatcher( double target,
@@ -40,6 +45,13 @@ namespace Matchers {
Detail::FloatingPointKind m_type; Detail::FloatingPointKind m_type;
}; };
//! Creates a matcher that accepts doubles within certain ULP range of target
WithinUlpsMatcher WithinULP(double target, uint64_t maxUlpDiff);
//! Creates a matcher that accepts floats within certain ULP range of target
WithinUlpsMatcher WithinULP(float target, uint64_t maxUlpDiff);
// Given IEEE-754 format for floats and doubles, we can assume // Given IEEE-754 format for floats and doubles, we can assume
// that float -> double promotion is lossless. Given this, we can // that float -> double promotion is lossless. Given this, we can
// assume that if we do the standard relative comparison of // assume that if we do the standard relative comparison of
@@ -56,13 +68,6 @@ namespace Matchers {
double m_epsilon; double m_epsilon;
}; };
//! Creates a matcher that accepts doubles within certain ULP range of target
WithinUlpsMatcher WithinULP(double target, uint64_t maxUlpDiff);
//! Creates a matcher that accepts floats within certain ULP range of target
WithinUlpsMatcher WithinULP(float target, uint64_t maxUlpDiff);
//! Creates a matcher that accepts numbers within certain range of target
WithinAbsMatcher WithinAbs(double target, double margin);
//! Creates a matcher that accepts doubles within certain relative range of target //! Creates a matcher that accepts doubles within certain relative range of target
WithinRelMatcher WithinRel(double target, double eps); WithinRelMatcher WithinRel(double target, double eps);
//! Creates a matcher that accepts doubles within 100*DBL_EPS relative range of target //! Creates a matcher that accepts doubles within 100*DBL_EPS relative range of target
@@ -72,6 +77,17 @@ namespace Matchers {
//! Creates a matcher that accepts floats within 100*FLT_EPS relative range of target //! Creates a matcher that accepts floats within 100*FLT_EPS relative range of target
WithinRelMatcher WithinRel(float target); WithinRelMatcher WithinRel(float target);
class IsNaNMatcher final : public MatcherBase<double> {
public:
IsNaNMatcher() = default;
bool match( double const& matchee ) const override;
std::string describe() const override;
};
IsNaNMatcher IsNaN();
} // namespace Matchers } // namespace Matchers
} // namespace Catch } // namespace Catch

View File

@@ -0,0 +1,144 @@
// Copyright Catch2 Authors
// Distributed under the Boost Software License, Version 1.0.
// (See accompanying file LICENSE.txt or copy at
// https://www.boost.org/LICENSE_1_0.txt)
// SPDX-License-Identifier: BSL-1.0
#ifndef CATCH_MATCHERS_RANGE_EQUALS_HPP_INCLUDED
#define CATCH_MATCHERS_RANGE_EQUALS_HPP_INCLUDED
#include <catch2/internal/catch_is_permutation.hpp>
#include <catch2/matchers/catch_matchers_templated.hpp>
#include <algorithm>
#include <utility>
namespace Catch {
namespace Matchers {
/**
* Matcher for checking that an element contains the same
* elements in the same order
*/
template <typename TargetRangeLike, typename Equality>
class RangeEqualsMatcher final : public MatcherGenericBase {
TargetRangeLike m_desired;
Equality m_predicate;
public:
template <typename TargetRangeLike2, typename Equality2>
RangeEqualsMatcher( TargetRangeLike2&& range,
Equality2&& predicate ):
m_desired( CATCH_FORWARD( range ) ),
m_predicate( CATCH_FORWARD( predicate ) ) {}
template <typename RangeLike>
bool match( RangeLike&& rng ) const {
auto rng_start = begin( rng );
const auto rng_end = end( rng );
auto target_start = begin( m_desired );
const auto target_end = end( m_desired );
while (rng_start != rng_end && target_start != target_end) {
if (!m_predicate(*rng_start, *target_start)) {
return false;
}
++rng_start;
++target_start;
}
return rng_start == rng_end && target_start == target_end;
}
std::string describe() const override {
return "elements are " + Catch::Detail::stringify( m_desired );
}
};
/**
* Matcher for checking that an element contains the same
* elements (but not necessarily in the same order)
*/
template <typename TargetRangeLike, typename Equality>
class UnorderedRangeEqualsMatcher final : public MatcherGenericBase {
TargetRangeLike m_desired;
Equality m_predicate;
public:
template <typename TargetRangeLike2, typename Equality2>
UnorderedRangeEqualsMatcher( TargetRangeLike2&& range,
Equality2&& predicate ):
m_desired( CATCH_FORWARD( range ) ),
m_predicate( CATCH_FORWARD( predicate ) ) {}
template <typename RangeLike>
bool match( RangeLike&& rng ) const {
using std::begin;
using std::end;
return Catch::Detail::is_permutation( begin( m_desired ),
end( m_desired ),
begin( rng ),
end( rng ),
m_predicate );
}
std::string describe() const override {
return "unordered elements are " +
::Catch::Detail::stringify( m_desired );
}
};
/**
* Creates a matcher that checks if all elements in a range are equal
* to all elements in another range.
*
* Uses `std::equal_to` to do the comparison
*/
template <typename RangeLike>
std::enable_if_t<!Detail::is_matcher<RangeLike>::value,
RangeEqualsMatcher<RangeLike, std::equal_to<>>>
RangeEquals( RangeLike&& range ) {
return { CATCH_FORWARD( range ), std::equal_to<>{} };
}
/**
* Creates a matcher that checks if all elements in a range are equal
* to all elements in another range.
*
* Uses to provided predicate `predicate` to do the comparisons
*/
template <typename RangeLike, typename Equality>
RangeEqualsMatcher<RangeLike, Equality>
RangeEquals( RangeLike&& range, Equality&& predicate ) {
return { CATCH_FORWARD( range ), CATCH_FORWARD( predicate ) };
}
/**
* Creates a matcher that checks if all elements in a range are equal
* to all elements in another range, in some permutation
*
* Uses `std::equal_to` to do the comparison
*/
template <typename RangeLike>
std::enable_if_t<
!Detail::is_matcher<RangeLike>::value,
UnorderedRangeEqualsMatcher<RangeLike, std::equal_to<>>>
UnorderedRangeEquals( RangeLike&& range ) {
return { CATCH_FORWARD( range ), std::equal_to<>{} };
}
/**
* Creates a matcher that checks if all elements in a range are equal
* to all elements in another range, in some permuation.
*
* Uses to provided predicate `predicate` to do the comparisons
*/
template <typename RangeLike, typename Equality>
UnorderedRangeEqualsMatcher<RangeLike, Equality>
UnorderedRangeEquals( RangeLike&& range, Equality&& predicate ) {
return { CATCH_FORWARD( range ), CATCH_FORWARD( predicate ) };
}
} // namespace Matchers
} // namespace Catch
#endif // CATCH_MATCHERS_RANGE_EQUALS_HPP_INCLUDED

View File

@@ -93,6 +93,7 @@ internal_headers = [
'internal/catch_floating_point_helpers.hpp', 'internal/catch_floating_point_helpers.hpp',
'internal/catch_getenv.hpp', 'internal/catch_getenv.hpp',
'internal/catch_istream.hpp', 'internal/catch_istream.hpp',
'internal/catch_is_permutation.hpp',
'internal/catch_lazy_expr.hpp', 'internal/catch_lazy_expr.hpp',
'internal/catch_leak_detector.hpp', 'internal/catch_leak_detector.hpp',
'internal/catch_list.hpp', 'internal/catch_list.hpp',

View File

@@ -17,7 +17,9 @@ namespace Catch {
void AutomakeReporter::testCaseEnded(TestCaseStats const& _testCaseStats) { void AutomakeReporter::testCaseEnded(TestCaseStats const& _testCaseStats) {
// Possible values to emit are PASS, XFAIL, SKIP, FAIL, XPASS and ERROR. // Possible values to emit are PASS, XFAIL, SKIP, FAIL, XPASS and ERROR.
m_stream << ":test-result: "; m_stream << ":test-result: ";
if (_testCaseStats.totals.assertions.allPassed()) { if ( _testCaseStats.totals.testCases.skipped > 0 ) {
m_stream << "SKIP";
} else if (_testCaseStats.totals.assertions.allPassed()) {
m_stream << "PASS"; m_stream << "PASS";
} else if (_testCaseStats.totals.assertions.allOk()) { } else if (_testCaseStats.totals.assertions.allOk()) {
m_stream << "XFAIL"; m_stream << "XFAIL";

View File

@@ -105,6 +105,11 @@ public:
printIssue("explicitly"); printIssue("explicitly");
printRemainingMessages(Colour::None); printRemainingMessages(Colour::None);
break; break;
case ResultWas::ExplicitSkip:
printResultType(Colour::Skip, "skipped"_sr);
printMessage();
printRemainingMessages();
break;
// These cases are here to prevent compiler warnings // These cases are here to prevent compiler warnings
case ResultWas::Unknown: case ResultWas::Unknown:
case ResultWas::FailureBit: case ResultWas::FailureBit:
@@ -187,7 +192,7 @@ private:
private: private:
std::ostream& stream; std::ostream& stream;
AssertionResult const& result; AssertionResult const& result;
std::vector<MessageInfo> messages; std::vector<MessageInfo> const& messages;
std::vector<MessageInfo>::const_iterator itMessage; std::vector<MessageInfo>::const_iterator itMessage;
bool printInfoMessages; bool printInfoMessages;
ColourImpl* colourImpl; ColourImpl* colourImpl;
@@ -220,7 +225,7 @@ private:
// Drop out if result was successful and we're not printing those // Drop out if result was successful and we're not printing those
if( !m_config->includeSuccessfulResults() && result.isOk() ) { if( !m_config->includeSuccessfulResults() && result.isOk() ) {
if( result.getResultType() != ResultWas::Warning ) if( result.getResultType() != ResultWas::Warning && result.getResultType() != ResultWas::ExplicitSkip )
return; return;
printInfoMessages = false; printInfoMessages = false;
} }

View File

@@ -51,7 +51,6 @@ public:
stats(_stats), stats(_stats),
result(_stats.assertionResult), result(_stats.assertionResult),
colour(Colour::None), colour(Colour::None),
message(result.getMessage()),
messages(_stats.infoMessages), messages(_stats.infoMessages),
colourImpl(colourImpl_), colourImpl(colourImpl_),
printInfoMessages(_printInfoMessages) { printInfoMessages(_printInfoMessages) {
@@ -60,10 +59,10 @@ public:
colour = Colour::Success; colour = Colour::Success;
passOrFail = "PASSED"_sr; passOrFail = "PASSED"_sr;
//if( result.hasMessage() ) //if( result.hasMessage() )
if (_stats.infoMessages.size() == 1) if (messages.size() == 1)
messageLabel = "with message"; messageLabel = "with message"_sr;
if (_stats.infoMessages.size() > 1) if (messages.size() > 1)
messageLabel = "with messages"; messageLabel = "with messages"_sr;
break; break;
case ResultWas::ExpressionFailed: case ResultWas::ExpressionFailed:
if (result.isOk()) { if (result.isOk()) {
@@ -73,43 +72,57 @@ public:
colour = Colour::Error; colour = Colour::Error;
passOrFail = "FAILED"_sr; passOrFail = "FAILED"_sr;
} }
if (_stats.infoMessages.size() == 1) if (messages.size() == 1)
messageLabel = "with message"; messageLabel = "with message"_sr;
if (_stats.infoMessages.size() > 1) if (messages.size() > 1)
messageLabel = "with messages"; messageLabel = "with messages"_sr;
break; break;
case ResultWas::ThrewException: case ResultWas::ThrewException:
colour = Colour::Error; colour = Colour::Error;
passOrFail = "FAILED"_sr; passOrFail = "FAILED"_sr;
messageLabel = "due to unexpected exception with "; // todo switch
if (_stats.infoMessages.size() == 1) switch (messages.size()) { case 0:
messageLabel += "message"; messageLabel = "due to unexpected exception with "_sr;
if (_stats.infoMessages.size() > 1) break;
messageLabel += "messages"; case 1:
messageLabel = "due to unexpected exception with message"_sr;
break;
default:
messageLabel = "due to unexpected exception with messages"_sr;
break;
}
break; break;
case ResultWas::FatalErrorCondition: case ResultWas::FatalErrorCondition:
colour = Colour::Error; colour = Colour::Error;
passOrFail = "FAILED"_sr; passOrFail = "FAILED"_sr;
messageLabel = "due to a fatal error condition"; messageLabel = "due to a fatal error condition"_sr;
break; break;
case ResultWas::DidntThrowException: case ResultWas::DidntThrowException:
colour = Colour::Error; colour = Colour::Error;
passOrFail = "FAILED"_sr; passOrFail = "FAILED"_sr;
messageLabel = "because no exception was thrown where one was expected"; messageLabel = "because no exception was thrown where one was expected"_sr;
break; break;
case ResultWas::Info: case ResultWas::Info:
messageLabel = "info"; messageLabel = "info"_sr;
break; break;
case ResultWas::Warning: case ResultWas::Warning:
messageLabel = "warning"; messageLabel = "warning"_sr;
break; break;
case ResultWas::ExplicitFailure: case ResultWas::ExplicitFailure:
passOrFail = "FAILED"_sr; passOrFail = "FAILED"_sr;
colour = Colour::Error; colour = Colour::Error;
if (_stats.infoMessages.size() == 1) if (messages.size() == 1)
messageLabel = "explicitly with message"; messageLabel = "explicitly with message"_sr;
if (_stats.infoMessages.size() > 1) if (messages.size() > 1)
messageLabel = "explicitly with messages"; messageLabel = "explicitly with messages"_sr;
break;
case ResultWas::ExplicitSkip:
colour = Colour::Skip;
passOrFail = "SKIPPED"_sr;
if (messages.size() == 1)
messageLabel = "explicitly with message"_sr;
if (messages.size() > 1)
messageLabel = "explicitly with messages"_sr;
break; break;
// These cases are here to prevent compiler warnings // These cases are here to prevent compiler warnings
case ResultWas::Unknown: case ResultWas::Unknown:
@@ -173,9 +186,8 @@ private:
AssertionResult const& result; AssertionResult const& result;
Colour::Code colour; Colour::Code colour;
StringRef passOrFail; StringRef passOrFail;
std::string messageLabel; StringRef messageLabel;
std::string message; std::vector<MessageInfo> const& messages;
std::vector<MessageInfo> messages;
ColourImpl* colourImpl; ColourImpl* colourImpl;
bool printInfoMessages; bool printInfoMessages;
}; };
@@ -185,13 +197,16 @@ std::size_t makeRatio( std::uint64_t number, std::uint64_t total ) {
return (ratio == 0 && number > 0) ? 1 : static_cast<std::size_t>(ratio); return (ratio == 0 && number > 0) ? 1 : static_cast<std::size_t>(ratio);
} }
std::size_t& findMax( std::size_t& i, std::size_t& j, std::size_t& k ) { std::size_t&
if (i > j && i > k) findMax( std::size_t& i, std::size_t& j, std::size_t& k, std::size_t& l ) {
if (i > j && i > k && i > l)
return i; return i;
else if (j > k) else if (j > k && j > l)
return j; return j;
else else if (k > l)
return k; return k;
else
return l;
} }
enum class Justification { Left, Right }; enum class Justification { Left, Right };
@@ -400,7 +415,8 @@ void ConsoleReporter::assertionEnded(AssertionStats const& _assertionStats) {
bool includeResults = m_config->includeSuccessfulResults() || !result.isOk(); bool includeResults = m_config->includeSuccessfulResults() || !result.isOk();
// Drop out if result was successful but we're not printing them. // Drop out if result was successful but we're not printing them.
if (!includeResults && result.getResultType() != ResultWas::Warning) // TODO: Make configurable whether skips should be printed
if (!includeResults && result.getResultType() != ResultWas::Warning && result.getResultType() != ResultWas::ExplicitSkip)
return; return;
lazyPrint(); lazyPrint();
@@ -603,10 +619,11 @@ void ConsoleReporter::printTotalsDivider(Totals const& totals) {
std::size_t failedRatio = makeRatio(totals.testCases.failed, totals.testCases.total()); std::size_t failedRatio = makeRatio(totals.testCases.failed, totals.testCases.total());
std::size_t failedButOkRatio = makeRatio(totals.testCases.failedButOk, totals.testCases.total()); std::size_t failedButOkRatio = makeRatio(totals.testCases.failedButOk, totals.testCases.total());
std::size_t passedRatio = makeRatio(totals.testCases.passed, totals.testCases.total()); std::size_t passedRatio = makeRatio(totals.testCases.passed, totals.testCases.total());
while (failedRatio + failedButOkRatio + passedRatio < CATCH_CONFIG_CONSOLE_WIDTH - 1) std::size_t skippedRatio = makeRatio(totals.testCases.skipped, totals.testCases.total());
findMax(failedRatio, failedButOkRatio, passedRatio)++; while (failedRatio + failedButOkRatio + passedRatio + skippedRatio < CATCH_CONFIG_CONSOLE_WIDTH - 1)
findMax(failedRatio, failedButOkRatio, passedRatio, skippedRatio)++;
while (failedRatio + failedButOkRatio + passedRatio > CATCH_CONFIG_CONSOLE_WIDTH - 1) while (failedRatio + failedButOkRatio + passedRatio > CATCH_CONFIG_CONSOLE_WIDTH - 1)
findMax(failedRatio, failedButOkRatio, passedRatio)--; findMax(failedRatio, failedButOkRatio, passedRatio, skippedRatio)--;
m_stream << m_colour->guardColour( Colour::Error ) m_stream << m_colour->guardColour( Colour::Error )
<< std::string( failedRatio, '=' ) << std::string( failedRatio, '=' )
@@ -619,6 +636,8 @@ void ConsoleReporter::printTotalsDivider(Totals const& totals) {
m_stream << m_colour->guardColour( Colour::Success ) m_stream << m_colour->guardColour( Colour::Success )
<< std::string( passedRatio, '=' ); << std::string( passedRatio, '=' );
} }
m_stream << m_colour->guardColour( Colour::Skip )
<< std::string( skippedRatio, '=' );
} else { } else {
m_stream << m_colour->guardColour( Colour::Warning ) m_stream << m_colour->guardColour( Colour::Warning )
<< std::string( CATCH_CONFIG_CONSOLE_WIDTH - 1, '=' ); << std::string( CATCH_CONFIG_CONSOLE_WIDTH - 1, '=' );

View File

@@ -70,7 +70,8 @@ namespace Catch {
void void
CumulativeReporterBase::sectionStarting( SectionInfo const& sectionInfo ) { CumulativeReporterBase::sectionStarting( SectionInfo const& sectionInfo ) {
SectionStats incompleteStats( sectionInfo, Counts(), 0, false ); // We need a copy, because SectionStats expect to take ownership
SectionStats incompleteStats( SectionInfo(sectionInfo), Counts(), 0, false );
SectionNode* node; SectionNode* node;
if ( m_sectionStack.empty() ) { if ( m_sectionStack.empty() ) {
if ( !m_rootSection ) { if ( !m_rootSection ) {

View File

@@ -316,15 +316,22 @@ namespace Catch {
} }
std::vector<SummaryColumn> columns; std::vector<SummaryColumn> columns;
// Don't include "skipped assertions" in total count
const auto totalAssertionCount =
totals.assertions.total() - totals.assertions.skipped;
columns.push_back( SummaryColumn( "", Colour::None ) columns.push_back( SummaryColumn( "", Colour::None )
.addRow( totals.testCases.total() ) .addRow( totals.testCases.total() )
.addRow( totals.assertions.total() ) ); .addRow( totalAssertionCount ) );
columns.push_back( SummaryColumn( "passed", Colour::Success ) columns.push_back( SummaryColumn( "passed", Colour::Success )
.addRow( totals.testCases.passed ) .addRow( totals.testCases.passed )
.addRow( totals.assertions.passed ) ); .addRow( totals.assertions.passed ) );
columns.push_back( SummaryColumn( "failed", Colour::ResultError ) columns.push_back( SummaryColumn( "failed", Colour::ResultError )
.addRow( totals.testCases.failed ) .addRow( totals.testCases.failed )
.addRow( totals.assertions.failed ) ); .addRow( totals.assertions.failed ) );
columns.push_back( SummaryColumn( "skipped", Colour::Skip )
.addRow( totals.testCases.skipped )
// Don't print "skipped assertions"
.addRow( 0 ) );
columns.push_back( columns.push_back(
SummaryColumn( "failed as expected", Colour::ResultExpectedFailure ) SummaryColumn( "failed as expected", Colour::ResultExpectedFailure )
.addRow( totals.testCases.failedButOk ) .addRow( totals.testCases.failedButOk )

View File

@@ -132,6 +132,7 @@ namespace Catch {
xml.writeAttribute( "name"_sr, stats.runInfo.name ); xml.writeAttribute( "name"_sr, stats.runInfo.name );
xml.writeAttribute( "errors"_sr, unexpectedExceptions ); xml.writeAttribute( "errors"_sr, unexpectedExceptions );
xml.writeAttribute( "failures"_sr, stats.totals.assertions.failed-unexpectedExceptions ); xml.writeAttribute( "failures"_sr, stats.totals.assertions.failed-unexpectedExceptions );
xml.writeAttribute( "skipped"_sr, stats.totals.assertions.skipped );
xml.writeAttribute( "tests"_sr, stats.totals.assertions.total() ); xml.writeAttribute( "tests"_sr, stats.totals.assertions.total() );
xml.writeAttribute( "hostname"_sr, "tbd"_sr ); // !TBD xml.writeAttribute( "hostname"_sr, "tbd"_sr ); // !TBD
if( m_config->showDurations() == ShowDurations::Never ) if( m_config->showDurations() == ShowDurations::Never )
@@ -244,7 +245,8 @@ namespace Catch {
void JunitReporter::writeAssertion( AssertionStats const& stats ) { void JunitReporter::writeAssertion( AssertionStats const& stats ) {
AssertionResult const& result = stats.assertionResult; AssertionResult const& result = stats.assertionResult;
if( !result.isOk() ) { if ( !result.isOk() ||
result.getResultType() == ResultWas::ExplicitSkip ) {
std::string elementName; std::string elementName;
switch( result.getResultType() ) { switch( result.getResultType() ) {
case ResultWas::ThrewException: case ResultWas::ThrewException:
@@ -256,7 +258,9 @@ namespace Catch {
case ResultWas::DidntThrowException: case ResultWas::DidntThrowException:
elementName = "failure"; elementName = "failure";
break; break;
case ResultWas::ExplicitSkip:
elementName = "skipped";
break;
// We should never see these here: // We should never see these here:
case ResultWas::Info: case ResultWas::Info:
case ResultWas::Warning: case ResultWas::Warning:
@@ -274,7 +278,9 @@ namespace Catch {
xml.writeAttribute( "type"_sr, result.getTestMacroName() ); xml.writeAttribute( "type"_sr, result.getTestMacroName() );
ReusableStringStream rss; ReusableStringStream rss;
if (stats.totals.assertions.total() > 0) { if ( result.getResultType() == ResultWas::ExplicitSkip ) {
rss << "SKIPPED\n";
} else {
rss << "FAILED" << ":\n"; rss << "FAILED" << ":\n";
if (result.hasExpression()) { if (result.hasExpression()) {
rss << " "; rss << " ";
@@ -285,8 +291,6 @@ namespace Catch {
rss << "with expansion:\n"; rss << "with expansion:\n";
rss << TextFlow::Column(result.getExpandedExpression()).indent(2) << '\n'; rss << TextFlow::Column(result.getExpandedExpression()).indent(2) << '\n';
} }
} else {
rss << '\n';
} }
if( !result.getMessage().empty() ) if( !result.getMessage().empty() )

View File

@@ -118,7 +118,7 @@ namespace Catch {
CATCH_INTERNAL_SUPPRESS_GLOBALS_WARNINGS \ CATCH_INTERNAL_SUPPRESS_GLOBALS_WARNINGS \
namespace { \ namespace { \
Catch::ListenerRegistrar<listenerType> INTERNAL_CATCH_UNIQUE_NAME( \ Catch::ListenerRegistrar<listenerType> INTERNAL_CATCH_UNIQUE_NAME( \
catch_internal_RegistrarFor )( #listenerType ); \ catch_internal_RegistrarFor )( #listenerType##_catch_sr ); \
} \ } \
CATCH_INTERNAL_STOP_WARNINGS_SUPPRESSION CATCH_INTERNAL_STOP_WARNINGS_SUPPRESSION

View File

@@ -40,7 +40,7 @@ namespace Catch {
} }
void SonarQubeReporter::writeRun( TestRunNode const& runNode ) { void SonarQubeReporter::writeRun( TestRunNode const& runNode ) {
std::map<std::string, std::vector<TestCaseNode const*>> testsPerFile; std::map<StringRef, std::vector<TestCaseNode const*>> testsPerFile;
for ( auto const& child : runNode.children ) { for ( auto const& child : runNode.children ) {
testsPerFile[child->value.testInfo->lineInfo.file].push_back( testsPerFile[child->value.testInfo->lineInfo.file].push_back(
@@ -52,7 +52,7 @@ namespace Catch {
} }
} }
void SonarQubeReporter::writeTestFile(std::string const& filename, std::vector<TestCaseNode const*> const& testCaseNodes) { void SonarQubeReporter::writeTestFile(StringRef filename, std::vector<TestCaseNode const*> const& testCaseNodes) {
XmlWriter::ScopedElement e = xml.scopedElement("file"); XmlWriter::ScopedElement e = xml.scopedElement("file");
xml.writeAttribute("path"_sr, filename); xml.writeAttribute("path"_sr, filename);
@@ -97,7 +97,8 @@ namespace Catch {
void SonarQubeReporter::writeAssertion(AssertionStats const& stats, bool okToFail) { void SonarQubeReporter::writeAssertion(AssertionStats const& stats, bool okToFail) {
AssertionResult const& result = stats.assertionResult; AssertionResult const& result = stats.assertionResult;
if (!result.isOk()) { if ( !result.isOk() ||
result.getResultType() == ResultWas::ExplicitSkip ) {
std::string elementName; std::string elementName;
if (okToFail) { if (okToFail) {
elementName = "skipped"; elementName = "skipped";
@@ -108,15 +109,13 @@ namespace Catch {
elementName = "error"; elementName = "error";
break; break;
case ResultWas::ExplicitFailure: case ResultWas::ExplicitFailure:
elementName = "failure";
break;
case ResultWas::ExpressionFailed: case ResultWas::ExpressionFailed:
elementName = "failure";
break;
case ResultWas::DidntThrowException: case ResultWas::DidntThrowException:
elementName = "failure"; elementName = "failure";
break; break;
case ResultWas::ExplicitSkip:
elementName = "skipped";
break;
// We should never see these here: // We should never see these here:
case ResultWas::Info: case ResultWas::Info:
case ResultWas::Warning: case ResultWas::Warning:
@@ -136,7 +135,9 @@ namespace Catch {
xml.writeAttribute("message"_sr, messageRss.str()); xml.writeAttribute("message"_sr, messageRss.str());
ReusableStringStream textRss; ReusableStringStream textRss;
if (stats.totals.assertions.total() > 0) { if ( result.getResultType() == ResultWas::ExplicitSkip ) {
textRss << "SKIPPED\n";
} else {
textRss << "FAILED:\n"; textRss << "FAILED:\n";
if (result.hasExpression()) { if (result.hasExpression()) {
textRss << '\t' << result.getExpressionInMacro() << '\n'; textRss << '\t' << result.getExpressionInMacro() << '\n';

View File

@@ -41,7 +41,7 @@ namespace Catch {
void writeRun( TestRunNode const& groupNode ); void writeRun( TestRunNode const& groupNode );
void writeTestFile(std::string const& filename, std::vector<TestCaseNode const*> const& testCaseNodes); void writeTestFile(StringRef filename, std::vector<TestCaseNode const*> const& testCaseNodes);
void writeTestCase(TestCaseNode const& testCaseNode); void writeTestCase(TestCaseNode const& testCaseNode);

View File

@@ -100,6 +100,12 @@ namespace Catch {
printIssue("explicitly"_sr); printIssue("explicitly"_sr);
printRemainingMessages(Colour::None); printRemainingMessages(Colour::None);
break; break;
case ResultWas::ExplicitSkip:
printResultType(tapPassedString);
printIssue(" # SKIP"_sr);
printMessage();
printRemainingMessages();
break;
// These cases are here to prevent compiler warnings // These cases are here to prevent compiler warnings
case ResultWas::Unknown: case ResultWas::Unknown:
case ResultWas::FailureBit: case ResultWas::FailureBit:
@@ -178,7 +184,7 @@ namespace Catch {
private: private:
std::ostream& stream; std::ostream& stream;
AssertionResult const& result; AssertionResult const& result;
std::vector<MessageInfo> messages; std::vector<MessageInfo> const& messages;
std::vector<MessageInfo>::const_iterator itMessage; std::vector<MessageInfo>::const_iterator itMessage;
bool printInfoMessages; bool printInfoMessages;
std::size_t counter; std::size_t counter;

View File

@@ -59,7 +59,8 @@ namespace Catch {
void TeamCityReporter::assertionEnded(AssertionStats const& assertionStats) { void TeamCityReporter::assertionEnded(AssertionStats const& assertionStats) {
AssertionResult const& result = assertionStats.assertionResult; AssertionResult const& result = assertionStats.assertionResult;
if (!result.isOk()) { if ( !result.isOk() ||
result.getResultType() == ResultWas::ExplicitSkip ) {
ReusableStringStream msg; ReusableStringStream msg;
if (!m_headerPrintedForThisSection) if (!m_headerPrintedForThisSection)
@@ -84,6 +85,9 @@ namespace Catch {
case ResultWas::ExplicitFailure: case ResultWas::ExplicitFailure:
msg << "explicit failure"; msg << "explicit failure";
break; break;
case ResultWas::ExplicitSkip:
msg << "explicit skip";
break;
// We shouldn't get here because of the isOk() test // We shouldn't get here because of the isOk() test
case ResultWas::Ok: case ResultWas::Ok:
@@ -111,18 +115,16 @@ namespace Catch {
" " << result.getExpandedExpression() << '\n'; " " << result.getExpandedExpression() << '\n';
} }
if (currentTestCaseInfo->okToFail()) { if ( result.getResultType() == ResultWas::ExplicitSkip ) {
m_stream << "##teamcity[testIgnored";
} else if ( currentTestCaseInfo->okToFail() ) {
msg << "- failure ignore as test marked as 'ok to fail'\n"; msg << "- failure ignore as test marked as 'ok to fail'\n";
m_stream << "##teamcity[testIgnored" m_stream << "##teamcity[testIgnored";
<< " name='" << escape(currentTestCaseInfo->name) << '\''
<< " message='" << escape(msg.str()) << '\''
<< "]\n";
} else { } else {
m_stream << "##teamcity[testFailed" m_stream << "##teamcity[testFailed";
<< " name='" << escape(currentTestCaseInfo->name) << '\''
<< " message='" << escape(msg.str()) << '\''
<< "]\n";
} }
m_stream << " name='" << escape( currentTestCaseInfo->name ) << '\''
<< " message='" << escape( msg.str() ) << '\'' << "]\n";
} }
m_stream.flush(); m_stream.flush();
} }

View File

@@ -66,7 +66,7 @@ namespace Catch {
void XmlReporter::testCaseStarting( TestCaseInfo const& testInfo ) { void XmlReporter::testCaseStarting( TestCaseInfo const& testInfo ) {
StreamingReporterBase::testCaseStarting(testInfo); StreamingReporterBase::testCaseStarting(testInfo);
m_xml.startElement( "TestCase" ) m_xml.startElement( "TestCase" )
.writeAttribute( "name"_sr, trim( testInfo.name ) ) .writeAttribute( "name"_sr, trim( StringRef(testInfo.name) ) )
.writeAttribute( "tags"_sr, testInfo.tagsAsString() ); .writeAttribute( "tags"_sr, testInfo.tagsAsString() );
writeSourceInfo( testInfo.lineInfo ); writeSourceInfo( testInfo.lineInfo );
@@ -80,7 +80,7 @@ namespace Catch {
StreamingReporterBase::sectionStarting( sectionInfo ); StreamingReporterBase::sectionStarting( sectionInfo );
if( m_sectionDepth++ > 0 ) { if( m_sectionDepth++ > 0 ) {
m_xml.startElement( "Section" ) m_xml.startElement( "Section" )
.writeAttribute( "name"_sr, trim( sectionInfo.name ) ); .writeAttribute( "name"_sr, trim( StringRef(sectionInfo.name) ) );
writeSourceInfo( sectionInfo.lineInfo ); writeSourceInfo( sectionInfo.lineInfo );
m_xml.ensureTagClosed(); m_xml.ensureTagClosed();
} }
@@ -108,9 +108,10 @@ namespace Catch {
} }
// Drop out if result was successful but we're not printing them. // Drop out if result was successful but we're not printing them.
if( !includeResults && result.getResultType() != ResultWas::Warning ) if ( !includeResults && result.getResultType() != ResultWas::Warning &&
result.getResultType() != ResultWas::ExplicitSkip ) {
return; return;
}
// Print the expression if there is one. // Print the expression if there is one.
if( result.hasExpression() ) { if( result.hasExpression() ) {
@@ -153,6 +154,12 @@ namespace Catch {
m_xml.writeText( result.getMessage() ); m_xml.writeText( result.getMessage() );
m_xml.endElement(); m_xml.endElement();
break; break;
case ResultWas::ExplicitSkip:
m_xml.startElement( "Skip" );
writeSourceInfo( result.getSourceInfo() );
m_xml.writeText( result.getMessage() );
m_xml.endElement();
break;
default: default:
break; break;
} }
@@ -163,15 +170,18 @@ namespace Catch {
void XmlReporter::sectionEnded( SectionStats const& sectionStats ) { void XmlReporter::sectionEnded( SectionStats const& sectionStats ) {
StreamingReporterBase::sectionEnded( sectionStats ); StreamingReporterBase::sectionEnded( sectionStats );
if( --m_sectionDepth > 0 ) { if ( --m_sectionDepth > 0 ) {
XmlWriter::ScopedElement e = m_xml.scopedElement( "OverallResults" ); {
e.writeAttribute( "successes"_sr, sectionStats.assertions.passed ); XmlWriter::ScopedElement e = m_xml.scopedElement( "OverallResults" );
e.writeAttribute( "failures"_sr, sectionStats.assertions.failed ); e.writeAttribute( "successes"_sr, sectionStats.assertions.passed );
e.writeAttribute( "expectedFailures"_sr, sectionStats.assertions.failedButOk ); e.writeAttribute( "failures"_sr, sectionStats.assertions.failed );
e.writeAttribute( "expectedFailures"_sr, sectionStats.assertions.failedButOk );
if ( m_config->showDurations() == ShowDurations::Always ) e.writeAttribute( "skipped"_sr, sectionStats.assertions.skipped > 0 );
e.writeAttribute( "durationInSeconds"_sr, sectionStats.durationInSeconds );
if ( m_config->showDurations() == ShowDurations::Always )
e.writeAttribute( "durationInSeconds"_sr, sectionStats.durationInSeconds );
}
// Ends assertion tag
m_xml.endElement(); m_xml.endElement();
} }
} }
@@ -180,14 +190,14 @@ namespace Catch {
StreamingReporterBase::testCaseEnded( testCaseStats ); StreamingReporterBase::testCaseEnded( testCaseStats );
XmlWriter::ScopedElement e = m_xml.scopedElement( "OverallResult" ); XmlWriter::ScopedElement e = m_xml.scopedElement( "OverallResult" );
e.writeAttribute( "success"_sr, testCaseStats.totals.assertions.allOk() ); e.writeAttribute( "success"_sr, testCaseStats.totals.assertions.allOk() );
e.writeAttribute( "skips"_sr, testCaseStats.totals.assertions.skipped );
if ( m_config->showDurations() == ShowDurations::Always ) if ( m_config->showDurations() == ShowDurations::Always )
e.writeAttribute( "durationInSeconds"_sr, m_testCaseTimer.getElapsedSeconds() ); e.writeAttribute( "durationInSeconds"_sr, m_testCaseTimer.getElapsedSeconds() );
if( !testCaseStats.stdOut.empty() ) if( !testCaseStats.stdOut.empty() )
m_xml.scopedElement( "StdOut" ).writeText( trim( testCaseStats.stdOut ), XmlFormatting::Newline ); m_xml.scopedElement( "StdOut" ).writeText( trim( StringRef(testCaseStats.stdOut) ), XmlFormatting::Newline );
if( !testCaseStats.stdErr.empty() ) if( !testCaseStats.stdErr.empty() )
m_xml.scopedElement( "StdErr" ).writeText( trim( testCaseStats.stdErr ), XmlFormatting::Newline ); m_xml.scopedElement( "StdErr" ).writeText( trim( StringRef(testCaseStats.stdErr) ), XmlFormatting::Newline );
m_xml.endElement(); m_xml.endElement();
} }
@@ -197,11 +207,13 @@ namespace Catch {
m_xml.scopedElement( "OverallResults" ) m_xml.scopedElement( "OverallResults" )
.writeAttribute( "successes"_sr, testRunStats.totals.assertions.passed ) .writeAttribute( "successes"_sr, testRunStats.totals.assertions.passed )
.writeAttribute( "failures"_sr, testRunStats.totals.assertions.failed ) .writeAttribute( "failures"_sr, testRunStats.totals.assertions.failed )
.writeAttribute( "expectedFailures"_sr, testRunStats.totals.assertions.failedButOk ); .writeAttribute( "expectedFailures"_sr, testRunStats.totals.assertions.failedButOk )
.writeAttribute( "skips"_sr, testRunStats.totals.assertions.skipped );
m_xml.scopedElement( "OverallResultsCases") m_xml.scopedElement( "OverallResultsCases")
.writeAttribute( "successes"_sr, testRunStats.totals.testCases.passed ) .writeAttribute( "successes"_sr, testRunStats.totals.testCases.passed )
.writeAttribute( "failures"_sr, testRunStats.totals.testCases.failed ) .writeAttribute( "failures"_sr, testRunStats.totals.testCases.failed )
.writeAttribute( "expectedFailures"_sr, testRunStats.totals.testCases.failedButOk ); .writeAttribute( "expectedFailures"_sr, testRunStats.totals.testCases.failedButOk )
.writeAttribute( "skips"_sr, testRunStats.totals.testCases.skipped );
m_xml.endElement(); m_xml.endElement();
} }

View File

@@ -77,6 +77,7 @@ endif(MSVC) #Temporary workaround
# Please keep these ordered alphabetically # Please keep these ordered alphabetically
set(TEST_SOURCES set(TEST_SOURCES
${SELF_TEST_DIR}/TestRegistrations.cpp ${SELF_TEST_DIR}/TestRegistrations.cpp
${SELF_TEST_DIR}/IntrospectiveTests/Algorithms.tests.cpp
${SELF_TEST_DIR}/IntrospectiveTests/Clara.tests.cpp ${SELF_TEST_DIR}/IntrospectiveTests/Clara.tests.cpp
${SELF_TEST_DIR}/IntrospectiveTests/CmdLine.tests.cpp ${SELF_TEST_DIR}/IntrospectiveTests/CmdLine.tests.cpp
${SELF_TEST_DIR}/IntrospectiveTests/CmdLineHelpers.tests.cpp ${SELF_TEST_DIR}/IntrospectiveTests/CmdLineHelpers.tests.cpp
@@ -116,6 +117,7 @@ set(TEST_SOURCES
${SELF_TEST_DIR}/UsageTests/Generators.tests.cpp ${SELF_TEST_DIR}/UsageTests/Generators.tests.cpp
${SELF_TEST_DIR}/UsageTests/Message.tests.cpp ${SELF_TEST_DIR}/UsageTests/Message.tests.cpp
${SELF_TEST_DIR}/UsageTests/Misc.tests.cpp ${SELF_TEST_DIR}/UsageTests/Misc.tests.cpp
${SELF_TEST_DIR}/UsageTests/Skip.tests.cpp
${SELF_TEST_DIR}/UsageTests/ToStringByte.tests.cpp ${SELF_TEST_DIR}/UsageTests/ToStringByte.tests.cpp
${SELF_TEST_DIR}/UsageTests/ToStringChrono.tests.cpp ${SELF_TEST_DIR}/UsageTests/ToStringChrono.tests.cpp
${SELF_TEST_DIR}/UsageTests/ToStringGeneral.tests.cpp ${SELF_TEST_DIR}/UsageTests/ToStringGeneral.tests.cpp
@@ -133,6 +135,7 @@ set(TEST_SOURCES
set(TEST_HEADERS set(TEST_HEADERS
${SELF_TEST_DIR}/helpers/parse_test_spec.hpp ${SELF_TEST_DIR}/helpers/parse_test_spec.hpp
${SELF_TEST_DIR}/helpers/range_test_helpers.hpp
${SELF_TEST_DIR}/helpers/type_with_lit_0_comparisons.hpp ${SELF_TEST_DIR}/helpers/type_with_lit_0_comparisons.hpp
) )
@@ -272,6 +275,10 @@ add_test(NAME TestSpecs::OverrideFailureWithNoMatchedTests
COMMAND $<TARGET_FILE:SelfTest> "___nonexistent_test___" --allow-running-no-tests COMMAND $<TARGET_FILE:SelfTest> "___nonexistent_test___" --allow-running-no-tests
) )
add_test(NAME TestSpecs::OverrideAllSkipFailure
COMMAND $<TARGET_FILE:SelfTest> "tests can be skipped dynamically at runtime" --allow-running-no-tests
)
add_test(NAME TestSpecs::NonMatchingTestSpecIsRoundTrippable add_test(NAME TestSpecs::NonMatchingTestSpecIsRoundTrippable
COMMAND $<TARGET_FILE:SelfTest> Tracker, "this test does not exist" "[nor does this tag]" COMMAND $<TARGET_FILE:SelfTest> Tracker, "this test does not exist" "[nor does this tag]"
) )

View File

@@ -488,15 +488,32 @@ set_tests_properties(TestSpecs::EmptySpecWithNoTestsFails
PROPERTIES PROPERTIES
WILL_FAIL ON WILL_FAIL ON
) )
add_test( add_test(
NAME TestSpecs::OverrideFailureWithEmptySpec NAME TestSpecs::OverrideFailureWithEmptySpec
COMMAND $<TARGET_FILE:NoTests> --allow-running-no-tests COMMAND $<TARGET_FILE:NoTests> --allow-running-no-tests
) )
add_test( add_test(
NAME List::Listeners::WorksWithoutRegisteredListeners NAME List::Listeners::WorksWithoutRegisteredListeners
COMMAND $<TARGET_FILE:NoTests> --list-listeners COMMAND $<TARGET_FILE:NoTests> --list-listeners
) )
add_executable(AllSkipped ${TESTS_DIR}/X93-AllSkipped.cpp)
target_link_libraries(AllSkipped PRIVATE Catch2::Catch2WithMain)
add_test(
NAME TestSpecs::SkippingAllTestsFails
COMMAND $<TARGET_FILE:AllSkipped>
)
set_tests_properties(TestSpecs::SkippingAllTestsFails
PROPERTIES
WILL_FAIL ON
)
set( EXTRA_TEST_BINARIES set( EXTRA_TEST_BINARIES
AllSkipped
PrefixedMacros PrefixedMacros
DisabledMacros DisabledMacros
DisabledExceptions-DefaultHandler DisabledExceptions-DefaultHandler

View File

@@ -0,0 +1,16 @@
// Copyright Catch2 Authors
// Distributed under the Boost Software License, Version 1.0.
// (See accompanying file LICENSE.txt or copy at
// https://www.boost.org/LICENSE_1_0.txt)
// SPDX-License-Identifier: BSL-1.0
#include <catch2/catch_test_macros.hpp>
TEST_CASE( "this test case is being skipped" ) { SKIP(); }
TEST_CASE( "all sections in this test case are being skipped" ) {
SECTION( "A" ) { SKIP(); }
SECTION( "B" ) { SKIP(); }
}

View File

@@ -25,6 +25,7 @@ Nor would this
:test-result: PASS #1954 - 7 arg template test case sig compiles - 5, 3, 1, 1, 1, 0, 0 :test-result: PASS #1954 - 7 arg template test case sig compiles - 5, 3, 1, 1, 1, 0, 0
:test-result: PASS #2152 - ULP checks between differently signed values were wrong - double :test-result: PASS #2152 - ULP checks between differently signed values were wrong - double
:test-result: PASS #2152 - ULP checks between differently signed values were wrong - float :test-result: PASS #2152 - ULP checks between differently signed values were wrong - float
:test-result: XFAIL #2615 - Throwing in constructor generator fails test case but does not abort
:test-result: XFAIL #748 - captures with unexpected exceptions :test-result: XFAIL #748 - captures with unexpected exceptions
:test-result: PASS #809 :test-result: PASS #809
:test-result: PASS #833 :test-result: PASS #833
@@ -142,6 +143,7 @@ Nor would this
:test-result: PASS Exception as a value (e.g. in REQUIRE_THROWS_MATCHES) can be stringified :test-result: PASS Exception as a value (e.g. in REQUIRE_THROWS_MATCHES) can be stringified
:test-result: FAIL Exception matchers that fail :test-result: FAIL Exception matchers that fail
:test-result: PASS Exception matchers that succeed :test-result: PASS Exception matchers that succeed
:test-result: PASS Exception message can be matched
:test-result: PASS Exception messages can be tested for :test-result: PASS Exception messages can be tested for
:test-result: PASS Exceptions matchers :test-result: PASS Exceptions matchers
:test-result: FAIL Expected exceptions that don't throw or unexpected exceptions fail the test :test-result: FAIL Expected exceptions that don't throw or unexpected exceptions fail the test
@@ -149,6 +151,7 @@ Nor would this
:test-result: FAIL FAIL does not require an argument :test-result: FAIL FAIL does not require an argument
:test-result: FAIL FAIL_CHECK does not abort the test :test-result: FAIL FAIL_CHECK does not abort the test
:test-result: PASS Factorials are computed :test-result: PASS Factorials are computed
:test-result: PASS Filter generator throws exception for empty generator
:test-result: PASS Floating point matchers: double :test-result: PASS Floating point matchers: double
:test-result: PASS Floating point matchers: float :test-result: PASS Floating point matchers: float
:test-result: PASS Generators -- adapters :test-result: PASS Generators -- adapters
@@ -268,6 +271,7 @@ Message from section two
:test-result: FAIL Thrown string literals are translated :test-result: FAIL Thrown string literals are translated
:test-result: PASS Tracker :test-result: PASS Tracker
:test-result: PASS Trim strings :test-result: PASS Trim strings
:test-result: PASS Type conversions of RangeEquals and similar
:test-result: FAIL Unexpected exceptions can be translated :test-result: FAIL Unexpected exceptions can be translated
:test-result: PASS Upcasting special member functions :test-result: PASS Upcasting special member functions
:test-result: PASS Usage of AllMatch range matcher :test-result: PASS Usage of AllMatch range matcher
@@ -276,6 +280,8 @@ Message from section two
:test-result: PASS Usage of AnyTrue range matcher :test-result: PASS Usage of AnyTrue range matcher
:test-result: PASS Usage of NoneMatch range matcher :test-result: PASS Usage of NoneMatch range matcher
:test-result: PASS Usage of NoneTrue range matcher :test-result: PASS Usage of NoneTrue range matcher
:test-result: PASS Usage of RangeEquals range matcher
:test-result: PASS Usage of UnorderedRangeEquals range matcher
:test-result: PASS Usage of the SizeIs range matcher :test-result: PASS Usage of the SizeIs range matcher
:test-result: PASS Use a custom approx :test-result: PASS Use a custom approx
:test-result: PASS Variadic macros :test-result: PASS Variadic macros
@@ -296,6 +302,7 @@ Message from section two
:test-result: PASS X/level/1/b :test-result: PASS X/level/1/b
:test-result: PASS XmlEncode :test-result: PASS XmlEncode
:test-result: PASS XmlWriter writes boolean attributes as true/false :test-result: PASS XmlWriter writes boolean attributes as true/false
:test-result: SKIP a succeeding test can still be skipped
:test-result: PASS analyse no analysis :test-result: PASS analyse no analysis
:test-result: PASS array<int, N> -> toString :test-result: PASS array<int, N> -> toString
:test-result: PASS benchmark function call :test-result: PASS benchmark function call
@@ -308,10 +315,14 @@ Message from section two
:test-result: PASS comparisons between const int variables :test-result: PASS comparisons between const int variables
:test-result: PASS comparisons between int variables :test-result: PASS comparisons between int variables
:test-result: PASS convertToBits :test-result: PASS convertToBits
:test-result: SKIP dynamic skipping works with generators
:test-result: PASS empty tags are not allowed :test-result: PASS empty tags are not allowed
:test-result: PASS erfc_inv :test-result: PASS erfc_inv
:test-result: PASS estimate_clock_resolution :test-result: PASS estimate_clock_resolution
:test-result: PASS even more nested SECTION tests :test-result: PASS even more nested SECTION tests
:test-result: XFAIL failed assertions before SKIP cause test case to fail
:test-result: XFAIL failing for some generator values causes entire test case to fail
:test-result: XFAIL failing in some unskipped sections causes entire test case to fail
:test-result: FAIL first tag :test-result: FAIL first tag
loose text artifact loose text artifact
:test-result: FAIL has printf :test-result: FAIL has printf
@@ -330,6 +341,10 @@ loose text artifact
:test-result: FAIL mix info, unscoped info and warning :test-result: FAIL mix info, unscoped info and warning
:test-result: FAIL more nested SECTION tests :test-result: FAIL more nested SECTION tests
:test-result: PASS nested SECTION tests :test-result: PASS nested SECTION tests
a!
b1!
!
:test-result: FAIL nested sections can be skipped dynamically at runtime
:test-result: PASS non streamable - with conv. op :test-result: PASS non streamable - with conv. op
:test-result: PASS non-copyable objects :test-result: PASS non-copyable objects
:test-result: PASS normal_cdf :test-result: PASS normal_cdf
@@ -351,9 +366,11 @@ loose text artifact
:test-result: PASS run_for_at_least, chronometer :test-result: PASS run_for_at_least, chronometer
:test-result: PASS run_for_at_least, int :test-result: PASS run_for_at_least, int
:test-result: FAIL second tag :test-result: FAIL second tag
:test-result: SKIP sections can be skipped dynamically at runtime
:test-result: FAIL send a single char to INFO :test-result: FAIL send a single char to INFO
:test-result: FAIL sends information to INFO :test-result: FAIL sends information to INFO
:test-result: PASS shortened hide tags are split apart :test-result: PASS shortened hide tags are split apart
:test-result: SKIP skipped tests can optionally provide a reason
:test-result: PASS splitString :test-result: PASS splitString
:test-result: FAIL stacks unscoped info in loops :test-result: FAIL stacks unscoped info in loops
:test-result: PASS startsWith :test-result: PASS startsWith
@@ -375,6 +392,7 @@ loose text artifact
:test-result: PASS strlen3 :test-result: PASS strlen3
:test-result: PASS tables :test-result: PASS tables
:test-result: PASS tags with dots in later positions are not parsed as hidden :test-result: PASS tags with dots in later positions are not parsed as hidden
:test-result: SKIP tests can be skipped dynamically at runtime
:test-result: FAIL thrown std::strings are translated :test-result: FAIL thrown std::strings are translated
:test-result: PASS toString on const wchar_t const pointer returns the string contents :test-result: PASS toString on const wchar_t const pointer returns the string contents
:test-result: PASS toString on const wchar_t pointer returns the string contents :test-result: PASS toString on const wchar_t pointer returns the string contents

View File

@@ -23,6 +23,7 @@
:test-result: PASS #1954 - 7 arg template test case sig compiles - 5, 3, 1, 1, 1, 0, 0 :test-result: PASS #1954 - 7 arg template test case sig compiles - 5, 3, 1, 1, 1, 0, 0
:test-result: PASS #2152 - ULP checks between differently signed values were wrong - double :test-result: PASS #2152 - ULP checks between differently signed values were wrong - double
:test-result: PASS #2152 - ULP checks between differently signed values were wrong - float :test-result: PASS #2152 - ULP checks between differently signed values were wrong - float
:test-result: XFAIL #2615 - Throwing in constructor generator fails test case but does not abort
:test-result: XFAIL #748 - captures with unexpected exceptions :test-result: XFAIL #748 - captures with unexpected exceptions
:test-result: PASS #809 :test-result: PASS #809
:test-result: PASS #833 :test-result: PASS #833
@@ -140,6 +141,7 @@
:test-result: PASS Exception as a value (e.g. in REQUIRE_THROWS_MATCHES) can be stringified :test-result: PASS Exception as a value (e.g. in REQUIRE_THROWS_MATCHES) can be stringified
:test-result: FAIL Exception matchers that fail :test-result: FAIL Exception matchers that fail
:test-result: PASS Exception matchers that succeed :test-result: PASS Exception matchers that succeed
:test-result: PASS Exception message can be matched
:test-result: PASS Exception messages can be tested for :test-result: PASS Exception messages can be tested for
:test-result: PASS Exceptions matchers :test-result: PASS Exceptions matchers
:test-result: FAIL Expected exceptions that don't throw or unexpected exceptions fail the test :test-result: FAIL Expected exceptions that don't throw or unexpected exceptions fail the test
@@ -147,6 +149,7 @@
:test-result: FAIL FAIL does not require an argument :test-result: FAIL FAIL does not require an argument
:test-result: FAIL FAIL_CHECK does not abort the test :test-result: FAIL FAIL_CHECK does not abort the test
:test-result: PASS Factorials are computed :test-result: PASS Factorials are computed
:test-result: PASS Filter generator throws exception for empty generator
:test-result: PASS Floating point matchers: double :test-result: PASS Floating point matchers: double
:test-result: PASS Floating point matchers: float :test-result: PASS Floating point matchers: float
:test-result: PASS Generators -- adapters :test-result: PASS Generators -- adapters
@@ -261,6 +264,7 @@
:test-result: FAIL Thrown string literals are translated :test-result: FAIL Thrown string literals are translated
:test-result: PASS Tracker :test-result: PASS Tracker
:test-result: PASS Trim strings :test-result: PASS Trim strings
:test-result: PASS Type conversions of RangeEquals and similar
:test-result: FAIL Unexpected exceptions can be translated :test-result: FAIL Unexpected exceptions can be translated
:test-result: PASS Upcasting special member functions :test-result: PASS Upcasting special member functions
:test-result: PASS Usage of AllMatch range matcher :test-result: PASS Usage of AllMatch range matcher
@@ -269,6 +273,8 @@
:test-result: PASS Usage of AnyTrue range matcher :test-result: PASS Usage of AnyTrue range matcher
:test-result: PASS Usage of NoneMatch range matcher :test-result: PASS Usage of NoneMatch range matcher
:test-result: PASS Usage of NoneTrue range matcher :test-result: PASS Usage of NoneTrue range matcher
:test-result: PASS Usage of RangeEquals range matcher
:test-result: PASS Usage of UnorderedRangeEquals range matcher
:test-result: PASS Usage of the SizeIs range matcher :test-result: PASS Usage of the SizeIs range matcher
:test-result: PASS Use a custom approx :test-result: PASS Use a custom approx
:test-result: PASS Variadic macros :test-result: PASS Variadic macros
@@ -289,6 +295,7 @@
:test-result: PASS X/level/1/b :test-result: PASS X/level/1/b
:test-result: PASS XmlEncode :test-result: PASS XmlEncode
:test-result: PASS XmlWriter writes boolean attributes as true/false :test-result: PASS XmlWriter writes boolean attributes as true/false
:test-result: SKIP a succeeding test can still be skipped
:test-result: PASS analyse no analysis :test-result: PASS analyse no analysis
:test-result: PASS array<int, N> -> toString :test-result: PASS array<int, N> -> toString
:test-result: PASS benchmark function call :test-result: PASS benchmark function call
@@ -301,10 +308,14 @@
:test-result: PASS comparisons between const int variables :test-result: PASS comparisons between const int variables
:test-result: PASS comparisons between int variables :test-result: PASS comparisons between int variables
:test-result: PASS convertToBits :test-result: PASS convertToBits
:test-result: SKIP dynamic skipping works with generators
:test-result: PASS empty tags are not allowed :test-result: PASS empty tags are not allowed
:test-result: PASS erfc_inv :test-result: PASS erfc_inv
:test-result: PASS estimate_clock_resolution :test-result: PASS estimate_clock_resolution
:test-result: PASS even more nested SECTION tests :test-result: PASS even more nested SECTION tests
:test-result: XFAIL failed assertions before SKIP cause test case to fail
:test-result: XFAIL failing for some generator values causes entire test case to fail
:test-result: XFAIL failing in some unskipped sections causes entire test case to fail
:test-result: FAIL first tag :test-result: FAIL first tag
:test-result: FAIL has printf :test-result: FAIL has printf
:test-result: PASS is_unary_function :test-result: PASS is_unary_function
@@ -322,6 +333,7 @@
:test-result: FAIL mix info, unscoped info and warning :test-result: FAIL mix info, unscoped info and warning
:test-result: FAIL more nested SECTION tests :test-result: FAIL more nested SECTION tests
:test-result: PASS nested SECTION tests :test-result: PASS nested SECTION tests
:test-result: FAIL nested sections can be skipped dynamically at runtime
:test-result: PASS non streamable - with conv. op :test-result: PASS non streamable - with conv. op
:test-result: PASS non-copyable objects :test-result: PASS non-copyable objects
:test-result: PASS normal_cdf :test-result: PASS normal_cdf
@@ -343,9 +355,11 @@
:test-result: PASS run_for_at_least, chronometer :test-result: PASS run_for_at_least, chronometer
:test-result: PASS run_for_at_least, int :test-result: PASS run_for_at_least, int
:test-result: FAIL second tag :test-result: FAIL second tag
:test-result: SKIP sections can be skipped dynamically at runtime
:test-result: FAIL send a single char to INFO :test-result: FAIL send a single char to INFO
:test-result: FAIL sends information to INFO :test-result: FAIL sends information to INFO
:test-result: PASS shortened hide tags are split apart :test-result: PASS shortened hide tags are split apart
:test-result: SKIP skipped tests can optionally provide a reason
:test-result: PASS splitString :test-result: PASS splitString
:test-result: FAIL stacks unscoped info in loops :test-result: FAIL stacks unscoped info in loops
:test-result: PASS startsWith :test-result: PASS startsWith
@@ -367,6 +381,7 @@
:test-result: PASS strlen3 :test-result: PASS strlen3
:test-result: PASS tables :test-result: PASS tables
:test-result: PASS tags with dots in later positions are not parsed as hidden :test-result: PASS tags with dots in later positions are not parsed as hidden
:test-result: SKIP tests can be skipped dynamically at runtime
:test-result: FAIL thrown std::strings are translated :test-result: FAIL thrown std::strings are translated
:test-result: PASS toString on const wchar_t const pointer returns the string contents :test-result: PASS toString on const wchar_t const pointer returns the string contents
:test-result: PASS toString on const wchar_t pointer returns the string contents :test-result: PASS toString on const wchar_t pointer returns the string contents

View File

@@ -84,6 +84,7 @@ Matchers.tests.cpp:<line number>: passed: smallest_non_zero, WithinULP( -smalles
Matchers.tests.cpp:<line number>: passed: smallest_non_zero, !WithinULP( -smallest_non_zero, 1 ) for: 0.0 not is within 1 ULPs of -4.9406564584124654e-324 ([-9.8813129168249309e-324, -0.0000000000000000e+00]) Matchers.tests.cpp:<line number>: passed: smallest_non_zero, !WithinULP( -smallest_non_zero, 1 ) for: 0.0 not is within 1 ULPs of -4.9406564584124654e-324 ([-9.8813129168249309e-324, -0.0000000000000000e+00])
Matchers.tests.cpp:<line number>: passed: smallest_non_zero, WithinULP( -smallest_non_zero, 2 ) for: 0.0f is within 2 ULPs of -1.40129846e-45f ([-4.20389539e-45, 1.40129846e-45]) Matchers.tests.cpp:<line number>: passed: smallest_non_zero, WithinULP( -smallest_non_zero, 2 ) for: 0.0f is within 2 ULPs of -1.40129846e-45f ([-4.20389539e-45, 1.40129846e-45])
Matchers.tests.cpp:<line number>: passed: smallest_non_zero, !WithinULP( -smallest_non_zero, 1 ) for: 0.0f not is within 1 ULPs of -1.40129846e-45f ([-2.80259693e-45, -0.00000000e+00]) Matchers.tests.cpp:<line number>: passed: smallest_non_zero, !WithinULP( -smallest_non_zero, 1 ) for: 0.0f not is within 1 ULPs of -1.40129846e-45f ([-2.80259693e-45, -0.00000000e+00])
Generators.tests.cpp:<line number>: failed: unexpected exception with message: 'failure to init'
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'
@@ -572,6 +573,10 @@ Matchers.tests.cpp:<line number>: failed: throwsSpecialException( 3 ), SpecialEx
Matchers.tests.cpp:<line number>: failed: throwsSpecialException( 4 ), SpecialException, ExceptionMatcher{ 1 } for: SpecialException::what special exception has value of 1 Matchers.tests.cpp:<line number>: failed: throwsSpecialException( 4 ), SpecialException, ExceptionMatcher{ 1 } for: SpecialException::what special exception has value of 1
Matchers.tests.cpp:<line number>: passed: throwsSpecialException( 1 ), SpecialException, ExceptionMatcher{ 1 } for: SpecialException::what special exception has value of 1 Matchers.tests.cpp:<line number>: passed: throwsSpecialException( 1 ), SpecialException, ExceptionMatcher{ 1 } for: SpecialException::what special exception has value of 1
Matchers.tests.cpp:<line number>: passed: throwsSpecialException( 2 ), SpecialException, ExceptionMatcher{ 2 } for: SpecialException::what special exception has value of 2 Matchers.tests.cpp:<line number>: passed: throwsSpecialException( 2 ), SpecialException, ExceptionMatcher{ 2 } for: SpecialException::what special exception has value of 2
Matchers.tests.cpp:<line number>: passed: throwsDerivedException(), DerivedException, MessageMatches( StartsWith( "Derived" ) ) for: DerivedException::what matches "starts with: "Derived""
Matchers.tests.cpp:<line number>: passed: throwsDerivedException(), DerivedException, MessageMatches( EndsWith( "::what" ) ) for: DerivedException::what matches "ends with: "::what""
Matchers.tests.cpp:<line number>: passed: throwsDerivedException(), DerivedException, MessageMatches( !StartsWith( "::what" ) ) for: DerivedException::what matches "not starts with: "::what""
Matchers.tests.cpp:<line number>: passed: throwsSpecialException( 2 ), SpecialException, MessageMatches( StartsWith( "Special" ) ) for: SpecialException::what matches "starts with: "Special""
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>: passed: thisThrows(), Equals( "expecteD Exception", Catch::CaseSensitive::No ) for: "expected exception" equals: "expected exception" (case insensitive) Exception.tests.cpp:<line number>: passed: thisThrows(), Equals( "expecteD Exception", Catch::CaseSensitive::No ) for: "expected exception" equals: "expected exception" (case insensitive)
Exception.tests.cpp:<line number>: passed: thisThrows(), StartsWith( "expected" ) for: "expected exception" starts with: "expected" Exception.tests.cpp:<line number>: passed: thisThrows(), StartsWith( "expected" ) for: "expected exception" starts with: "expected"
@@ -594,6 +599,7 @@ Misc.tests.cpp:<line number>: passed: Factorial(1) == 1 for: 1 == 1
Misc.tests.cpp:<line number>: passed: Factorial(2) == 2 for: 2 == 2 Misc.tests.cpp:<line number>: passed: Factorial(2) == 2 for: 2 == 2
Misc.tests.cpp:<line number>: passed: Factorial(3) == 6 for: 6 == 6 Misc.tests.cpp:<line number>: passed: Factorial(3) == 6 for: 6 == 6
Misc.tests.cpp:<line number>: passed: Factorial(10) == 3628800 for: 3628800 (0x<hex digits>) == 3628800 (0x<hex digits>) Misc.tests.cpp:<line number>: passed: Factorial(10) == 3628800 for: 3628800 (0x<hex digits>) == 3628800 (0x<hex digits>)
GeneratorsImpl.tests.cpp:<line number>: passed: filter( []( int ) { return false; }, value( 3 ) ), Catch::GeneratorException
Matchers.tests.cpp:<line number>: passed: 10., WithinRel( 11.1, 0.1 ) for: 10.0 and 11.1 are within 10% of each other Matchers.tests.cpp:<line number>: passed: 10., WithinRel( 11.1, 0.1 ) for: 10.0 and 11.1 are within 10% of each other
Matchers.tests.cpp:<line number>: passed: 10., !WithinRel( 11.2, 0.1 ) for: 10.0 not and 11.2 are within 10% of each other Matchers.tests.cpp:<line number>: passed: 10., !WithinRel( 11.2, 0.1 ) for: 10.0 not and 11.2 are within 10% of each other
Matchers.tests.cpp:<line number>: passed: 1., !WithinRel( 0., 0.99 ) for: 1.0 not and 0 are within 99% of each other Matchers.tests.cpp:<line number>: passed: 1., !WithinRel( 0., 0.99 ) for: 1.0 not and 0 are within 99% of each other
@@ -623,6 +629,7 @@ Matchers.tests.cpp:<line number>: passed: WithinULP( 1., 0 )
Matchers.tests.cpp:<line number>: passed: WithinRel( 1., 0. ) Matchers.tests.cpp:<line number>: passed: WithinRel( 1., 0. )
Matchers.tests.cpp:<line number>: passed: WithinRel( 1., -0.2 ), std::domain_error Matchers.tests.cpp:<line number>: passed: WithinRel( 1., -0.2 ), std::domain_error
Matchers.tests.cpp:<line number>: passed: WithinRel( 1., 1. ), std::domain_error Matchers.tests.cpp:<line number>: passed: WithinRel( 1., 1. ), std::domain_error
Matchers.tests.cpp:<line number>: passed: 1., !IsNaN() for: 1.0 not is NaN
Matchers.tests.cpp:<line number>: passed: 10.f, WithinRel( 11.1f, 0.1f ) for: 10.0f and 11.1 are within 10% of each other Matchers.tests.cpp:<line number>: passed: 10.f, WithinRel( 11.1f, 0.1f ) for: 10.0f and 11.1 are within 10% of each other
Matchers.tests.cpp:<line number>: passed: 10.f, !WithinRel( 11.2f, 0.1f ) for: 10.0f not and 11.2 are within 10% of each other Matchers.tests.cpp:<line number>: passed: 10.f, !WithinRel( 11.2f, 0.1f ) for: 10.0f not and 11.2 are within 10% of each other
Matchers.tests.cpp:<line number>: passed: 1.f, !WithinRel( 0.f, 0.99f ) for: 1.0f not and 0 are within 99% of each other Matchers.tests.cpp:<line number>: passed: 1.f, !WithinRel( 0.f, 0.99f ) for: 1.0f not and 0 are within 99% of each other
@@ -655,6 +662,7 @@ Matchers.tests.cpp:<line number>: passed: WithinULP( 1.f, static_cast<uint64_t>(
Matchers.tests.cpp:<line number>: passed: WithinRel( 1.f, 0.f ) Matchers.tests.cpp:<line number>: passed: WithinRel( 1.f, 0.f )
Matchers.tests.cpp:<line number>: passed: WithinRel( 1.f, -0.2f ), std::domain_error Matchers.tests.cpp:<line number>: passed: WithinRel( 1.f, -0.2f ), std::domain_error
Matchers.tests.cpp:<line number>: passed: WithinRel( 1.f, 1.f ), std::domain_error Matchers.tests.cpp:<line number>: passed: WithinRel( 1.f, 1.f ), std::domain_error
Matchers.tests.cpp:<line number>: passed: 1., !IsNaN() for: 1.0 not is NaN
Generators.tests.cpp:<line number>: passed: i % 2 == 0 for: 0 == 0 Generators.tests.cpp:<line number>: passed: i % 2 == 0 for: 0 == 0
Generators.tests.cpp:<line number>: passed: i % 2 == 0 for: 0 == 0 Generators.tests.cpp:<line number>: passed: i % 2 == 0 for: 0 == 0
Generators.tests.cpp:<line number>: passed: i % 2 == 0 for: 0 == 0 Generators.tests.cpp:<line number>: passed: i % 2 == 0 for: 0 == 0
@@ -1855,6 +1863,23 @@ There is no extra whitespace here
StringManip.tests.cpp:<line number>: passed: trim(StringRef(whitespace_at_both_ends)) == StringRef(no_whitespace) for: There is no extra whitespace here StringManip.tests.cpp:<line number>: passed: trim(StringRef(whitespace_at_both_ends)) == StringRef(no_whitespace) for: There is no extra whitespace here
== ==
There is no extra whitespace here There is no extra whitespace here
MatchersRanges.tests.cpp:<line number>: passed: array_int_a, RangeEquals( c_array ) for: { 1, 2, 3 } elements are { 1, 2, 3 }
MatchersRanges.tests.cpp:<line number>: passed: array_int_a, UnorderedRangeEquals( c_array ) for: { 1, 2, 3 } unordered elements are { 1, 2, 3 }
MatchersRanges.tests.cpp:<line number>: passed: array_int_3, !RangeEquals( array_int_4 ) for: { 1, 2, 3 } not elements are { 1, 2, 3, 4 }
MatchersRanges.tests.cpp:<line number>: passed: array_int_3, !UnorderedRangeEquals( array_int_4 ) for: { 1, 2, 3 } not unordered elements are { 1, 2, 3, 4 }
MatchersRanges.tests.cpp:<line number>: passed: array_int_a, RangeEquals( vector_char_a ) for: { 1, 2, 3 } elements are { 1, 2, 3 }
MatchersRanges.tests.cpp:<line number>: passed: array_int_a, UnorderedRangeEquals( vector_char_a ) for: { 1, 2, 3 } unordered elements are { 1, 2, 3 }
MatchersRanges.tests.cpp:<line number>: passed: with 1 message: 'ContainerIsRandomAccess( array_int_a ) != ContainerIsRandomAccess( list_char_a )'
MatchersRanges.tests.cpp:<line number>: passed: array_int_a, RangeEquals( list_char_a ) for: { 1, 2, 3 } elements are { 1, 2, 3 }
MatchersRanges.tests.cpp:<line number>: passed: array_int_a, UnorderedRangeEquals( list_char_a ) for: { 1, 2, 3 } unordered elements are { 1, 2, 3 }
MatchersRanges.tests.cpp:<line number>: passed: vector_int_a, RangeEquals( vector_char_a ) for: { 1, 2, 3 } elements are { 1, 2, 3 }
MatchersRanges.tests.cpp:<line number>: passed: vector_int_a, UnorderedRangeEquals( vector_char_a ) for: { 1, 2, 3 } unordered elements are { 1, 2, 3 }
MatchersRanges.tests.cpp:<line number>: passed: vector_int_a, !RangeEquals( vector_char_b ) for: { 1, 2, 3 } not elements are { 1, 2, 2 }
MatchersRanges.tests.cpp:<line number>: passed: vector_int_a, !UnorderedRangeEquals( vector_char_b ) for: { 1, 2, 3 } not unordered elements are { 1, 2, 2 }
MatchersRanges.tests.cpp:<line number>: passed: a, !RangeEquals( b ) for: { 1, 2, 3 } not elements are { 3, 2, 1 }
MatchersRanges.tests.cpp:<line number>: passed: a, UnorderedRangeEquals( b ) for: { 1, 2, 3 } unordered elements are { 3, 2, 1 }
MatchersRanges.tests.cpp:<line number>: passed: vector_a, RangeEquals( array_a_plus_1, close_enough ) for: { 1, 2, 3 } elements are { 2, 3, 4 }
MatchersRanges.tests.cpp:<line number>: passed: vector_a, UnorderedRangeEquals( array_a_plus_1, close_enough ) for: { 1, 2, 3 } unordered elements are { 2, 3, 4 }
Exception.tests.cpp:<line number>: failed: unexpected exception with message: '3.14' Exception.tests.cpp:<line number>: failed: unexpected exception with message: '3.14'
UniquePtr.tests.cpp:<line number>: passed: bptr->i == 3 for: 3 == 3 UniquePtr.tests.cpp:<line number>: passed: bptr->i == 3 for: 3 == 3
UniquePtr.tests.cpp:<line number>: passed: bptr->i == 3 for: 3 == 3 UniquePtr.tests.cpp:<line number>: passed: bptr->i == 3 for: 3 == 3
@@ -1960,6 +1985,38 @@ MatchersRanges.tests.cpp:<line number>: passed: mocked.m_derefed[1] for: true
MatchersRanges.tests.cpp:<line number>: passed: mocked.m_derefed[2] for: true MatchersRanges.tests.cpp:<line number>: passed: mocked.m_derefed[2] for: true
MatchersRanges.tests.cpp:<line number>: passed: !(mocked.m_derefed[3]) for: !false MatchersRanges.tests.cpp:<line number>: passed: !(mocked.m_derefed[3]) for: !false
MatchersRanges.tests.cpp:<line number>: passed: !(mocked.m_derefed[4]) for: !false MatchersRanges.tests.cpp:<line number>: passed: !(mocked.m_derefed[4]) for: !false
MatchersRanges.tests.cpp:<line number>: passed: empty_vector, RangeEquals( empty_vector ) for: { } elements are { }
MatchersRanges.tests.cpp:<line number>: passed: empty_vector, !RangeEquals( non_empty_vector ) for: { } not elements are { 1 }
MatchersRanges.tests.cpp:<line number>: passed: non_empty_vector, !RangeEquals( empty_vector ) for: { 1 } not elements are { }
MatchersRanges.tests.cpp:<line number>: passed: non_empty_array, RangeEquals( non_empty_array ) for: { 1 } elements are { 1 }
MatchersRanges.tests.cpp:<line number>: passed: array_a, RangeEquals( array_a ) for: { 1, 2, 3 } elements are { 1, 2, 3 }
MatchersRanges.tests.cpp:<line number>: passed: array_a, !RangeEquals( array_b ) for: { 1, 2, 3 } not elements are { 2, 2, 3 }
MatchersRanges.tests.cpp:<line number>: passed: array_a, !RangeEquals( array_c ) for: { 1, 2, 3 } not elements are { 1, 2, 2 }
MatchersRanges.tests.cpp:<line number>: passed: vector_a, !RangeEquals( vector_b ) for: { 1, 2, 3 } not elements are { 1, 2, 3, 4 }
MatchersRanges.tests.cpp:<line number>: passed: vector_a, RangeEquals( vector_a_plus_1, close_enough ) for: { 1, 2, 3 } elements are { 2, 3, 4 }
MatchersRanges.tests.cpp:<line number>: passed: vector_a, !RangeEquals( vector_b, close_enough ) for: { 1, 2, 3 } not elements are { 3, 3, 4 }
MatchersRanges.tests.cpp:<line number>: passed: needs_adl1, RangeEquals( needs_adl2 ) for: { 1, 2, 3, 4, 5 } elements are { 1, 2, 3, 4, 5 }
MatchersRanges.tests.cpp:<line number>: passed: needs_adl1, RangeEquals( needs_adl3, []( int l, int r ) { return l + 1 == r; } ) for: { 1, 2, 3, 4, 5 } elements are { 2, 3, 4, 5, 6 }
MatchersRanges.tests.cpp:<line number>: passed: mocked1, !RangeEquals( arr ) for: { 1, 2, 3, 4 } not elements are { 1, 2, 4, 4 }
MatchersRanges.tests.cpp:<line number>: passed: mocked1.m_derefed[0] for: true
MatchersRanges.tests.cpp:<line number>: passed: mocked1.m_derefed[1] for: true
MatchersRanges.tests.cpp:<line number>: passed: mocked1.m_derefed[2] for: true
MatchersRanges.tests.cpp:<line number>: passed: !(mocked1.m_derefed[3]) for: !false
MatchersRanges.tests.cpp:<line number>: passed: mocked1, RangeEquals( arr ) for: { 1, 2, 3, 4 } elements are { 1, 2, 3, 4 }
MatchersRanges.tests.cpp:<line number>: passed: mocked1.m_derefed[0] for: true
MatchersRanges.tests.cpp:<line number>: passed: mocked1.m_derefed[1] for: true
MatchersRanges.tests.cpp:<line number>: passed: mocked1.m_derefed[2] for: true
MatchersRanges.tests.cpp:<line number>: passed: mocked1.m_derefed[3] for: true
MatchersRanges.tests.cpp:<line number>: passed: empty_vector, UnorderedRangeEquals( empty_vector ) for: { } unordered elements are { }
MatchersRanges.tests.cpp:<line number>: passed: empty_vector, !UnorderedRangeEquals( non_empty_vector ) for: { } not unordered elements are { 1 }
MatchersRanges.tests.cpp:<line number>: passed: non_empty_vector, !UnorderedRangeEquals( empty_vector ) for: { 1 } not unordered elements are { }
MatchersRanges.tests.cpp:<line number>: passed: non_empty_array, UnorderedRangeEquals( non_empty_array ) for: { 1 } unordered elements are { 1 }
MatchersRanges.tests.cpp:<line number>: passed: array_a, UnorderedRangeEquals( array_a ) for: { 1, 2, 3 } unordered elements are { 1, 2, 3 }
MatchersRanges.tests.cpp:<line number>: passed: array_a, !UnorderedRangeEquals( array_b ) for: { 1, 2, 3 } not unordered elements are { 2, 2, 3 }
MatchersRanges.tests.cpp:<line number>: passed: vector_a, !UnorderedRangeEquals( vector_b ) for: { 1, 2, 3 } not unordered elements are { 1, 2, 3, 4 }
MatchersRanges.tests.cpp:<line number>: passed: vector_a, UnorderedRangeEquals( vector_a_plus_1, close_enough ) for: { 1, 10, 20 } unordered elements are { 11, 21, 2 }
MatchersRanges.tests.cpp:<line number>: passed: vector_a, !UnorderedRangeEquals( vector_b, close_enough ) for: { 1, 10, 21 } not unordered elements are { 11, 21, 3 }
MatchersRanges.tests.cpp:<line number>: passed: needs_adl1, UnorderedRangeEquals( needs_adl2 ) for: { 1, 2, 3, 4, 5 } unordered elements are { 1, 2, 3, 4, 5 }
MatchersRanges.tests.cpp:<line number>: passed: empty_vec, SizeIs(0) for: { } has size == 0 MatchersRanges.tests.cpp:<line number>: passed: empty_vec, SizeIs(0) for: { } has size == 0
MatchersRanges.tests.cpp:<line number>: passed: empty_vec, !SizeIs(2) for: { } not has size == 2 MatchersRanges.tests.cpp:<line number>: passed: empty_vec, !SizeIs(2) for: { } not has size == 2
MatchersRanges.tests.cpp:<line number>: passed: empty_vec, SizeIs(Lt(2)) for: { } size matches is less than 2 MatchersRanges.tests.cpp:<line number>: passed: empty_vec, SizeIs(Lt(2)) for: { } size matches is less than 2
@@ -2056,6 +2113,8 @@ Xml.tests.cpp:<line number>: passed: encode( "[\x7F]" ) == "[\\x7F]" for: "[\x7F
Xml.tests.cpp:<line number>: passed: stream.str(), ContainsSubstring(R"(attr1="true")") && ContainsSubstring(R"(attr2="false")") for: "<?xml version="1.0" encoding="UTF-8"?> Xml.tests.cpp:<line number>: passed: stream.str(), ContainsSubstring(R"(attr1="true")") && ContainsSubstring(R"(attr2="false")") for: "<?xml version="1.0" encoding="UTF-8"?>
<Element1 attr1="true" attr2="false"/> <Element1 attr1="true" attr2="false"/>
" ( contains: "attr1="true"" and contains: "attr2="false"" ) " ( contains: "attr1="true"" and contains: "attr2="false"" )
Skip.tests.cpp:<line number>: passed:
Skip.tests.cpp:<line number>: skipped:
InternalBenchmark.tests.cpp:<line number>: passed: analysis.mean.point.count() == 23 for: 23.0 == 23 InternalBenchmark.tests.cpp:<line number>: passed: analysis.mean.point.count() == 23 for: 23.0 == 23
InternalBenchmark.tests.cpp:<line number>: passed: analysis.mean.lower_bound.count() == 23 for: 23.0 == 23 InternalBenchmark.tests.cpp:<line number>: passed: analysis.mean.lower_bound.count() == 23 for: 23.0 == 23
InternalBenchmark.tests.cpp:<line number>: passed: analysis.mean.upper_bound.count() == 23 for: 23.0 == 23 InternalBenchmark.tests.cpp:<line number>: passed: analysis.mean.upper_bound.count() == 23 for: 23.0 == 23
@@ -2145,6 +2204,9 @@ FloatingPoint.tests.cpp:<line number>: passed: convertToBits( -0. ) == ( 1ULL <<
9223372036854775808 (0x<hex digits>) 9223372036854775808 (0x<hex digits>)
FloatingPoint.tests.cpp:<line number>: passed: convertToBits( std::numeric_limits<float>::denorm_min() ) == 1 for: 1 == 1 FloatingPoint.tests.cpp:<line number>: passed: convertToBits( std::numeric_limits<float>::denorm_min() ) == 1 for: 1 == 1
FloatingPoint.tests.cpp:<line number>: passed: convertToBits( std::numeric_limits<double>::denorm_min() ) == 1 for: 1 == 1 FloatingPoint.tests.cpp:<line number>: passed: convertToBits( std::numeric_limits<double>::denorm_min() ) == 1 for: 1 == 1
Skip.tests.cpp:<line number>: skipped: 'skipping because answer = 41'
Skip.tests.cpp:<line number>: passed:
Skip.tests.cpp:<line number>: skipped: 'skipping because answer = 43'
Tag.tests.cpp:<line number>: passed: Catch::TestCaseInfo("", { "test with an empty tag", "[]" }, dummySourceLineInfo) Tag.tests.cpp:<line number>: passed: Catch::TestCaseInfo("", { "test with an empty tag", "[]" }, dummySourceLineInfo)
InternalBenchmark.tests.cpp:<line number>: passed: erfc_inv(1.103560) == Approx(-0.09203687623843015) for: -0.0920368762 == Approx( -0.0920368762 ) InternalBenchmark.tests.cpp:<line number>: passed: erfc_inv(1.103560) == Approx(-0.09203687623843015) for: -0.0920368762 == Approx( -0.0920368762 )
InternalBenchmark.tests.cpp:<line number>: passed: erfc_inv(1.067400) == Approx(-0.05980291115763361) for: -0.0598029112 == Approx( -0.0598029112 ) InternalBenchmark.tests.cpp:<line number>: passed: erfc_inv(1.067400) == Approx(-0.05980291115763361) for: -0.0598029112 == Approx( -0.0598029112 )
@@ -2154,6 +2216,14 @@ InternalBenchmark.tests.cpp:<line number>: passed: res.outliers.total() == 0 for
Misc.tests.cpp:<line number>: passed: Misc.tests.cpp:<line number>: passed:
Misc.tests.cpp:<line number>: passed: Misc.tests.cpp:<line number>: passed:
Misc.tests.cpp:<line number>: passed: Misc.tests.cpp:<line number>: passed:
Skip.tests.cpp:<line number>: failed: 3 == 4
Skip.tests.cpp:<line number>: skipped:
Skip.tests.cpp:<line number>: failed: explicitly
Skip.tests.cpp:<line number>: skipped:
Skip.tests.cpp:<line number>: failed: explicitly
Skip.tests.cpp:<line number>: skipped:
Skip.tests.cpp:<line number>: skipped:
Skip.tests.cpp:<line number>: failed: explicitly
loose text artifact loose text artifact
Clara.tests.cpp:<line number>: passed: with 1 message: 'Catch::Clara::Detail::is_unary_function<decltype(unary1)>::value' Clara.tests.cpp:<line number>: passed: with 1 message: 'Catch::Clara::Detail::is_unary_function<decltype(unary1)>::value'
Clara.tests.cpp:<line number>: passed: with 1 message: 'Catch::Clara::Detail::is_unary_function<decltype(unary2)>::value' Clara.tests.cpp:<line number>: passed: with 1 message: 'Catch::Clara::Detail::is_unary_function<decltype(unary2)>::value'
@@ -2211,6 +2281,10 @@ Misc.tests.cpp:<line number>: passed: a < b for: 1 < 2
Misc.tests.cpp:<line number>: passed: a != b for: 1 != 2 Misc.tests.cpp:<line number>: passed: a != b for: 1 != 2
Misc.tests.cpp:<line number>: passed: b != a for: 2 != 1 Misc.tests.cpp:<line number>: passed: b != a for: 2 != 1
Misc.tests.cpp:<line number>: passed: a != b for: 1 != 2 Misc.tests.cpp:<line number>: passed: a != b for: 1 != 2
a!
b1!
Skip.tests.cpp:<line number>: skipped:
!
Tricky.tests.cpp:<line number>: passed: s == "7" for: "7" == "7" Tricky.tests.cpp:<line number>: passed: s == "7" for: "7" == "7"
Tricky.tests.cpp:<line number>: passed: ti == typeid(int) for: {?} == {?} Tricky.tests.cpp:<line number>: passed: ti == typeid(int) for: {?} == {?}
InternalBenchmark.tests.cpp:<line number>: passed: normal_cdf(0.000000) == Approx(0.50000000000000000) for: 0.5 == Approx( 0.5 ) InternalBenchmark.tests.cpp:<line number>: passed: normal_cdf(0.000000) == Approx(0.50000000000000000) for: 0.5 == Approx( 0.5 )
@@ -2295,9 +2369,13 @@ InternalBenchmark.tests.cpp:<line number>: passed: x >= old_x for: 128 >= 64
InternalBenchmark.tests.cpp:<line number>: passed: Timing.elapsed >= time for: 128 ns >= 100 ns InternalBenchmark.tests.cpp:<line number>: passed: Timing.elapsed >= time for: 128 ns >= 100 ns
InternalBenchmark.tests.cpp:<line number>: passed: Timing.result == Timing.iterations + 17 for: 145 == 145 InternalBenchmark.tests.cpp:<line number>: passed: Timing.result == Timing.iterations + 17 for: 145 == 145
InternalBenchmark.tests.cpp:<line number>: passed: Timing.iterations >= time.count() for: 128 >= 100 InternalBenchmark.tests.cpp:<line number>: passed: Timing.iterations >= time.count() for: 128 >= 100
Skip.tests.cpp:<line number>: passed:
Skip.tests.cpp:<line number>: skipped:
Skip.tests.cpp:<line number>: passed:
Misc.tests.cpp:<line number>: failed: false with 1 message: '3' Misc.tests.cpp:<line number>: failed: false with 1 message: '3'
Message.tests.cpp:<line number>: failed: false with 2 messages: 'hi' and 'i := 7' Message.tests.cpp:<line number>: failed: false with 2 messages: 'hi' and 'i := 7'
Tag.tests.cpp:<line number>: passed: testcase.tags, VectorContains( Tag( "magic-tag" ) ) && VectorContains( Tag( "."_catch_sr ) ) for: { {?}, {?} } ( Contains: {?} and Contains: {?} ) Tag.tests.cpp:<line number>: passed: testcase.tags, VectorContains( Tag( "magic-tag" ) ) && VectorContains( Tag( "."_catch_sr ) ) for: { {?}, {?} } ( Contains: {?} and Contains: {?} )
Skip.tests.cpp:<line number>: skipped: 'skipping because answer = 43'
StringManip.tests.cpp:<line number>: passed: splitStringRef("", ','), Equals(std::vector<StringRef>()) for: { } Equals: { } StringManip.tests.cpp:<line number>: passed: splitStringRef("", ','), Equals(std::vector<StringRef>()) for: { } Equals: { }
StringManip.tests.cpp:<line number>: passed: splitStringRef("abc", ','), Equals(std::vector<StringRef>{"abc"}) for: { abc } Equals: { abc } StringManip.tests.cpp:<line number>: passed: splitStringRef("abc", ','), Equals(std::vector<StringRef>{"abc"}) for: { abc } Equals: { abc }
StringManip.tests.cpp:<line number>: passed: splitStringRef("abc,def", ','), Equals(std::vector<StringRef>{"abc", "def"}) for: { abc, def } Equals: { abc, def } StringManip.tests.cpp:<line number>: passed: splitStringRef("abc,def", ','), Equals(std::vector<StringRef>{"abc", "def"}) for: { abc, def } Equals: { abc, def }
@@ -2363,6 +2441,7 @@ Generators.tests.cpp:<line number>: passed: strlen(std::get<0>(data)) == static_
Generators.tests.cpp:<line number>: passed: strlen(std::get<0>(data)) == static_cast<size_t>(std::get<1>(data)) for: 6 == 6 Generators.tests.cpp:<line number>: passed: strlen(std::get<0>(data)) == static_cast<size_t>(std::get<1>(data)) for: 6 == 6
Tag.tests.cpp:<line number>: passed: testcase.tags.size() == 1 for: 1 == 1 Tag.tests.cpp:<line number>: passed: testcase.tags.size() == 1 for: 1 == 1
Tag.tests.cpp:<line number>: passed: testcase.tags[0].original == "magic.tag"_catch_sr for: magic.tag == magic.tag Tag.tests.cpp:<line number>: passed: testcase.tags[0].original == "magic.tag"_catch_sr for: magic.tag == magic.tag
Skip.tests.cpp:<line number>: skipped:
Exception.tests.cpp:<line number>: failed: unexpected exception with message: 'Why would you throw a std::string?' Exception.tests.cpp:<line number>: failed: unexpected exception with message: 'Why would you throw a std::string?'
Misc.tests.cpp:<line number>: passed: result == "\"wide load\"" for: ""wide load"" == ""wide load"" Misc.tests.cpp:<line number>: passed: result == "\"wide load\"" for: ""wide load"" == ""wide load""
Misc.tests.cpp:<line number>: passed: result == "\"wide load\"" for: ""wide load"" == ""wide load"" Misc.tests.cpp:<line number>: passed: result == "\"wide load\"" for: ""wide load"" == ""wide load""
@@ -2459,7 +2538,7 @@ InternalBenchmark.tests.cpp:<line number>: passed: med == 18. for: 18.0 == 18.0
InternalBenchmark.tests.cpp:<line number>: passed: q3 == 23. for: 23.0 == 23.0 InternalBenchmark.tests.cpp:<line number>: passed: q3 == 23. for: 23.0 == 23.0
Misc.tests.cpp:<line number>: passed: Misc.tests.cpp:<line number>: passed:
Misc.tests.cpp:<line number>: passed: Misc.tests.cpp:<line number>: passed:
test cases: 394 | 304 passed | 83 failed | 7 failed as expected test cases: 409 | 309 passed | 84 failed | 5 skipped | 11 failed as expected
assertions: 2159 | 1989 passed | 143 failed | 27 failed as expected assertions: 2226 | 2049 passed | 145 failed | 32 failed as expected

View File

@@ -82,6 +82,7 @@ Matchers.tests.cpp:<line number>: passed: smallest_non_zero, WithinULP( -smalles
Matchers.tests.cpp:<line number>: passed: smallest_non_zero, !WithinULP( -smallest_non_zero, 1 ) for: 0.0 not is within 1 ULPs of -4.9406564584124654e-324 ([-9.8813129168249309e-324, -0.0000000000000000e+00]) Matchers.tests.cpp:<line number>: passed: smallest_non_zero, !WithinULP( -smallest_non_zero, 1 ) for: 0.0 not is within 1 ULPs of -4.9406564584124654e-324 ([-9.8813129168249309e-324, -0.0000000000000000e+00])
Matchers.tests.cpp:<line number>: passed: smallest_non_zero, WithinULP( -smallest_non_zero, 2 ) for: 0.0f is within 2 ULPs of -1.40129846e-45f ([-4.20389539e-45, 1.40129846e-45]) Matchers.tests.cpp:<line number>: passed: smallest_non_zero, WithinULP( -smallest_non_zero, 2 ) for: 0.0f is within 2 ULPs of -1.40129846e-45f ([-4.20389539e-45, 1.40129846e-45])
Matchers.tests.cpp:<line number>: passed: smallest_non_zero, !WithinULP( -smallest_non_zero, 1 ) for: 0.0f not is within 1 ULPs of -1.40129846e-45f ([-2.80259693e-45, -0.00000000e+00]) Matchers.tests.cpp:<line number>: passed: smallest_non_zero, !WithinULP( -smallest_non_zero, 1 ) for: 0.0f not is within 1 ULPs of -1.40129846e-45f ([-2.80259693e-45, -0.00000000e+00])
Generators.tests.cpp:<line number>: failed: unexpected exception with message: 'failure to init'
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'
@@ -570,6 +571,10 @@ Matchers.tests.cpp:<line number>: failed: throwsSpecialException( 3 ), SpecialEx
Matchers.tests.cpp:<line number>: failed: throwsSpecialException( 4 ), SpecialException, ExceptionMatcher{ 1 } for: SpecialException::what special exception has value of 1 Matchers.tests.cpp:<line number>: failed: throwsSpecialException( 4 ), SpecialException, ExceptionMatcher{ 1 } for: SpecialException::what special exception has value of 1
Matchers.tests.cpp:<line number>: passed: throwsSpecialException( 1 ), SpecialException, ExceptionMatcher{ 1 } for: SpecialException::what special exception has value of 1 Matchers.tests.cpp:<line number>: passed: throwsSpecialException( 1 ), SpecialException, ExceptionMatcher{ 1 } for: SpecialException::what special exception has value of 1
Matchers.tests.cpp:<line number>: passed: throwsSpecialException( 2 ), SpecialException, ExceptionMatcher{ 2 } for: SpecialException::what special exception has value of 2 Matchers.tests.cpp:<line number>: passed: throwsSpecialException( 2 ), SpecialException, ExceptionMatcher{ 2 } for: SpecialException::what special exception has value of 2
Matchers.tests.cpp:<line number>: passed: throwsDerivedException(), DerivedException, MessageMatches( StartsWith( "Derived" ) ) for: DerivedException::what matches "starts with: "Derived""
Matchers.tests.cpp:<line number>: passed: throwsDerivedException(), DerivedException, MessageMatches( EndsWith( "::what" ) ) for: DerivedException::what matches "ends with: "::what""
Matchers.tests.cpp:<line number>: passed: throwsDerivedException(), DerivedException, MessageMatches( !StartsWith( "::what" ) ) for: DerivedException::what matches "not starts with: "::what""
Matchers.tests.cpp:<line number>: passed: throwsSpecialException( 2 ), SpecialException, MessageMatches( StartsWith( "Special" ) ) for: SpecialException::what matches "starts with: "Special""
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>: passed: thisThrows(), Equals( "expecteD Exception", Catch::CaseSensitive::No ) for: "expected exception" equals: "expected exception" (case insensitive) Exception.tests.cpp:<line number>: passed: thisThrows(), Equals( "expecteD Exception", Catch::CaseSensitive::No ) for: "expected exception" equals: "expected exception" (case insensitive)
Exception.tests.cpp:<line number>: passed: thisThrows(), StartsWith( "expected" ) for: "expected exception" starts with: "expected" Exception.tests.cpp:<line number>: passed: thisThrows(), StartsWith( "expected" ) for: "expected exception" starts with: "expected"
@@ -592,6 +597,7 @@ Misc.tests.cpp:<line number>: passed: Factorial(1) == 1 for: 1 == 1
Misc.tests.cpp:<line number>: passed: Factorial(2) == 2 for: 2 == 2 Misc.tests.cpp:<line number>: passed: Factorial(2) == 2 for: 2 == 2
Misc.tests.cpp:<line number>: passed: Factorial(3) == 6 for: 6 == 6 Misc.tests.cpp:<line number>: passed: Factorial(3) == 6 for: 6 == 6
Misc.tests.cpp:<line number>: passed: Factorial(10) == 3628800 for: 3628800 (0x<hex digits>) == 3628800 (0x<hex digits>) Misc.tests.cpp:<line number>: passed: Factorial(10) == 3628800 for: 3628800 (0x<hex digits>) == 3628800 (0x<hex digits>)
GeneratorsImpl.tests.cpp:<line number>: passed: filter( []( int ) { return false; }, value( 3 ) ), Catch::GeneratorException
Matchers.tests.cpp:<line number>: passed: 10., WithinRel( 11.1, 0.1 ) for: 10.0 and 11.1 are within 10% of each other Matchers.tests.cpp:<line number>: passed: 10., WithinRel( 11.1, 0.1 ) for: 10.0 and 11.1 are within 10% of each other
Matchers.tests.cpp:<line number>: passed: 10., !WithinRel( 11.2, 0.1 ) for: 10.0 not and 11.2 are within 10% of each other Matchers.tests.cpp:<line number>: passed: 10., !WithinRel( 11.2, 0.1 ) for: 10.0 not and 11.2 are within 10% of each other
Matchers.tests.cpp:<line number>: passed: 1., !WithinRel( 0., 0.99 ) for: 1.0 not and 0 are within 99% of each other Matchers.tests.cpp:<line number>: passed: 1., !WithinRel( 0., 0.99 ) for: 1.0 not and 0 are within 99% of each other
@@ -621,6 +627,7 @@ Matchers.tests.cpp:<line number>: passed: WithinULP( 1., 0 )
Matchers.tests.cpp:<line number>: passed: WithinRel( 1., 0. ) Matchers.tests.cpp:<line number>: passed: WithinRel( 1., 0. )
Matchers.tests.cpp:<line number>: passed: WithinRel( 1., -0.2 ), std::domain_error Matchers.tests.cpp:<line number>: passed: WithinRel( 1., -0.2 ), std::domain_error
Matchers.tests.cpp:<line number>: passed: WithinRel( 1., 1. ), std::domain_error Matchers.tests.cpp:<line number>: passed: WithinRel( 1., 1. ), std::domain_error
Matchers.tests.cpp:<line number>: passed: 1., !IsNaN() for: 1.0 not is NaN
Matchers.tests.cpp:<line number>: passed: 10.f, WithinRel( 11.1f, 0.1f ) for: 10.0f and 11.1 are within 10% of each other Matchers.tests.cpp:<line number>: passed: 10.f, WithinRel( 11.1f, 0.1f ) for: 10.0f and 11.1 are within 10% of each other
Matchers.tests.cpp:<line number>: passed: 10.f, !WithinRel( 11.2f, 0.1f ) for: 10.0f not and 11.2 are within 10% of each other Matchers.tests.cpp:<line number>: passed: 10.f, !WithinRel( 11.2f, 0.1f ) for: 10.0f not and 11.2 are within 10% of each other
Matchers.tests.cpp:<line number>: passed: 1.f, !WithinRel( 0.f, 0.99f ) for: 1.0f not and 0 are within 99% of each other Matchers.tests.cpp:<line number>: passed: 1.f, !WithinRel( 0.f, 0.99f ) for: 1.0f not and 0 are within 99% of each other
@@ -653,6 +660,7 @@ Matchers.tests.cpp:<line number>: passed: WithinULP( 1.f, static_cast<uint64_t>(
Matchers.tests.cpp:<line number>: passed: WithinRel( 1.f, 0.f ) Matchers.tests.cpp:<line number>: passed: WithinRel( 1.f, 0.f )
Matchers.tests.cpp:<line number>: passed: WithinRel( 1.f, -0.2f ), std::domain_error Matchers.tests.cpp:<line number>: passed: WithinRel( 1.f, -0.2f ), std::domain_error
Matchers.tests.cpp:<line number>: passed: WithinRel( 1.f, 1.f ), std::domain_error Matchers.tests.cpp:<line number>: passed: WithinRel( 1.f, 1.f ), std::domain_error
Matchers.tests.cpp:<line number>: passed: 1., !IsNaN() for: 1.0 not is NaN
Generators.tests.cpp:<line number>: passed: i % 2 == 0 for: 0 == 0 Generators.tests.cpp:<line number>: passed: i % 2 == 0 for: 0 == 0
Generators.tests.cpp:<line number>: passed: i % 2 == 0 for: 0 == 0 Generators.tests.cpp:<line number>: passed: i % 2 == 0 for: 0 == 0
Generators.tests.cpp:<line number>: passed: i % 2 == 0 for: 0 == 0 Generators.tests.cpp:<line number>: passed: i % 2 == 0 for: 0 == 0
@@ -1848,6 +1856,23 @@ There is no extra whitespace here
StringManip.tests.cpp:<line number>: passed: trim(StringRef(whitespace_at_both_ends)) == StringRef(no_whitespace) for: There is no extra whitespace here StringManip.tests.cpp:<line number>: passed: trim(StringRef(whitespace_at_both_ends)) == StringRef(no_whitespace) for: There is no extra whitespace here
== ==
There is no extra whitespace here There is no extra whitespace here
MatchersRanges.tests.cpp:<line number>: passed: array_int_a, RangeEquals( c_array ) for: { 1, 2, 3 } elements are { 1, 2, 3 }
MatchersRanges.tests.cpp:<line number>: passed: array_int_a, UnorderedRangeEquals( c_array ) for: { 1, 2, 3 } unordered elements are { 1, 2, 3 }
MatchersRanges.tests.cpp:<line number>: passed: array_int_3, !RangeEquals( array_int_4 ) for: { 1, 2, 3 } not elements are { 1, 2, 3, 4 }
MatchersRanges.tests.cpp:<line number>: passed: array_int_3, !UnorderedRangeEquals( array_int_4 ) for: { 1, 2, 3 } not unordered elements are { 1, 2, 3, 4 }
MatchersRanges.tests.cpp:<line number>: passed: array_int_a, RangeEquals( vector_char_a ) for: { 1, 2, 3 } elements are { 1, 2, 3 }
MatchersRanges.tests.cpp:<line number>: passed: array_int_a, UnorderedRangeEquals( vector_char_a ) for: { 1, 2, 3 } unordered elements are { 1, 2, 3 }
MatchersRanges.tests.cpp:<line number>: passed: with 1 message: 'ContainerIsRandomAccess( array_int_a ) != ContainerIsRandomAccess( list_char_a )'
MatchersRanges.tests.cpp:<line number>: passed: array_int_a, RangeEquals( list_char_a ) for: { 1, 2, 3 } elements are { 1, 2, 3 }
MatchersRanges.tests.cpp:<line number>: passed: array_int_a, UnorderedRangeEquals( list_char_a ) for: { 1, 2, 3 } unordered elements are { 1, 2, 3 }
MatchersRanges.tests.cpp:<line number>: passed: vector_int_a, RangeEquals( vector_char_a ) for: { 1, 2, 3 } elements are { 1, 2, 3 }
MatchersRanges.tests.cpp:<line number>: passed: vector_int_a, UnorderedRangeEquals( vector_char_a ) for: { 1, 2, 3 } unordered elements are { 1, 2, 3 }
MatchersRanges.tests.cpp:<line number>: passed: vector_int_a, !RangeEquals( vector_char_b ) for: { 1, 2, 3 } not elements are { 1, 2, 2 }
MatchersRanges.tests.cpp:<line number>: passed: vector_int_a, !UnorderedRangeEquals( vector_char_b ) for: { 1, 2, 3 } not unordered elements are { 1, 2, 2 }
MatchersRanges.tests.cpp:<line number>: passed: a, !RangeEquals( b ) for: { 1, 2, 3 } not elements are { 3, 2, 1 }
MatchersRanges.tests.cpp:<line number>: passed: a, UnorderedRangeEquals( b ) for: { 1, 2, 3 } unordered elements are { 3, 2, 1 }
MatchersRanges.tests.cpp:<line number>: passed: vector_a, RangeEquals( array_a_plus_1, close_enough ) for: { 1, 2, 3 } elements are { 2, 3, 4 }
MatchersRanges.tests.cpp:<line number>: passed: vector_a, UnorderedRangeEquals( array_a_plus_1, close_enough ) for: { 1, 2, 3 } unordered elements are { 2, 3, 4 }
Exception.tests.cpp:<line number>: failed: unexpected exception with message: '3.14' Exception.tests.cpp:<line number>: failed: unexpected exception with message: '3.14'
UniquePtr.tests.cpp:<line number>: passed: bptr->i == 3 for: 3 == 3 UniquePtr.tests.cpp:<line number>: passed: bptr->i == 3 for: 3 == 3
UniquePtr.tests.cpp:<line number>: passed: bptr->i == 3 for: 3 == 3 UniquePtr.tests.cpp:<line number>: passed: bptr->i == 3 for: 3 == 3
@@ -1953,6 +1978,38 @@ MatchersRanges.tests.cpp:<line number>: passed: mocked.m_derefed[1] for: true
MatchersRanges.tests.cpp:<line number>: passed: mocked.m_derefed[2] for: true MatchersRanges.tests.cpp:<line number>: passed: mocked.m_derefed[2] for: true
MatchersRanges.tests.cpp:<line number>: passed: !(mocked.m_derefed[3]) for: !false MatchersRanges.tests.cpp:<line number>: passed: !(mocked.m_derefed[3]) for: !false
MatchersRanges.tests.cpp:<line number>: passed: !(mocked.m_derefed[4]) for: !false MatchersRanges.tests.cpp:<line number>: passed: !(mocked.m_derefed[4]) for: !false
MatchersRanges.tests.cpp:<line number>: passed: empty_vector, RangeEquals( empty_vector ) for: { } elements are { }
MatchersRanges.tests.cpp:<line number>: passed: empty_vector, !RangeEquals( non_empty_vector ) for: { } not elements are { 1 }
MatchersRanges.tests.cpp:<line number>: passed: non_empty_vector, !RangeEquals( empty_vector ) for: { 1 } not elements are { }
MatchersRanges.tests.cpp:<line number>: passed: non_empty_array, RangeEquals( non_empty_array ) for: { 1 } elements are { 1 }
MatchersRanges.tests.cpp:<line number>: passed: array_a, RangeEquals( array_a ) for: { 1, 2, 3 } elements are { 1, 2, 3 }
MatchersRanges.tests.cpp:<line number>: passed: array_a, !RangeEquals( array_b ) for: { 1, 2, 3 } not elements are { 2, 2, 3 }
MatchersRanges.tests.cpp:<line number>: passed: array_a, !RangeEquals( array_c ) for: { 1, 2, 3 } not elements are { 1, 2, 2 }
MatchersRanges.tests.cpp:<line number>: passed: vector_a, !RangeEquals( vector_b ) for: { 1, 2, 3 } not elements are { 1, 2, 3, 4 }
MatchersRanges.tests.cpp:<line number>: passed: vector_a, RangeEquals( vector_a_plus_1, close_enough ) for: { 1, 2, 3 } elements are { 2, 3, 4 }
MatchersRanges.tests.cpp:<line number>: passed: vector_a, !RangeEquals( vector_b, close_enough ) for: { 1, 2, 3 } not elements are { 3, 3, 4 }
MatchersRanges.tests.cpp:<line number>: passed: needs_adl1, RangeEquals( needs_adl2 ) for: { 1, 2, 3, 4, 5 } elements are { 1, 2, 3, 4, 5 }
MatchersRanges.tests.cpp:<line number>: passed: needs_adl1, RangeEquals( needs_adl3, []( int l, int r ) { return l + 1 == r; } ) for: { 1, 2, 3, 4, 5 } elements are { 2, 3, 4, 5, 6 }
MatchersRanges.tests.cpp:<line number>: passed: mocked1, !RangeEquals( arr ) for: { 1, 2, 3, 4 } not elements are { 1, 2, 4, 4 }
MatchersRanges.tests.cpp:<line number>: passed: mocked1.m_derefed[0] for: true
MatchersRanges.tests.cpp:<line number>: passed: mocked1.m_derefed[1] for: true
MatchersRanges.tests.cpp:<line number>: passed: mocked1.m_derefed[2] for: true
MatchersRanges.tests.cpp:<line number>: passed: !(mocked1.m_derefed[3]) for: !false
MatchersRanges.tests.cpp:<line number>: passed: mocked1, RangeEquals( arr ) for: { 1, 2, 3, 4 } elements are { 1, 2, 3, 4 }
MatchersRanges.tests.cpp:<line number>: passed: mocked1.m_derefed[0] for: true
MatchersRanges.tests.cpp:<line number>: passed: mocked1.m_derefed[1] for: true
MatchersRanges.tests.cpp:<line number>: passed: mocked1.m_derefed[2] for: true
MatchersRanges.tests.cpp:<line number>: passed: mocked1.m_derefed[3] for: true
MatchersRanges.tests.cpp:<line number>: passed: empty_vector, UnorderedRangeEquals( empty_vector ) for: { } unordered elements are { }
MatchersRanges.tests.cpp:<line number>: passed: empty_vector, !UnorderedRangeEquals( non_empty_vector ) for: { } not unordered elements are { 1 }
MatchersRanges.tests.cpp:<line number>: passed: non_empty_vector, !UnorderedRangeEquals( empty_vector ) for: { 1 } not unordered elements are { }
MatchersRanges.tests.cpp:<line number>: passed: non_empty_array, UnorderedRangeEquals( non_empty_array ) for: { 1 } unordered elements are { 1 }
MatchersRanges.tests.cpp:<line number>: passed: array_a, UnorderedRangeEquals( array_a ) for: { 1, 2, 3 } unordered elements are { 1, 2, 3 }
MatchersRanges.tests.cpp:<line number>: passed: array_a, !UnorderedRangeEquals( array_b ) for: { 1, 2, 3 } not unordered elements are { 2, 2, 3 }
MatchersRanges.tests.cpp:<line number>: passed: vector_a, !UnorderedRangeEquals( vector_b ) for: { 1, 2, 3 } not unordered elements are { 1, 2, 3, 4 }
MatchersRanges.tests.cpp:<line number>: passed: vector_a, UnorderedRangeEquals( vector_a_plus_1, close_enough ) for: { 1, 10, 20 } unordered elements are { 11, 21, 2 }
MatchersRanges.tests.cpp:<line number>: passed: vector_a, !UnorderedRangeEquals( vector_b, close_enough ) for: { 1, 10, 21 } not unordered elements are { 11, 21, 3 }
MatchersRanges.tests.cpp:<line number>: passed: needs_adl1, UnorderedRangeEquals( needs_adl2 ) for: { 1, 2, 3, 4, 5 } unordered elements are { 1, 2, 3, 4, 5 }
MatchersRanges.tests.cpp:<line number>: passed: empty_vec, SizeIs(0) for: { } has size == 0 MatchersRanges.tests.cpp:<line number>: passed: empty_vec, SizeIs(0) for: { } has size == 0
MatchersRanges.tests.cpp:<line number>: passed: empty_vec, !SizeIs(2) for: { } not has size == 2 MatchersRanges.tests.cpp:<line number>: passed: empty_vec, !SizeIs(2) for: { } not has size == 2
MatchersRanges.tests.cpp:<line number>: passed: empty_vec, SizeIs(Lt(2)) for: { } size matches is less than 2 MatchersRanges.tests.cpp:<line number>: passed: empty_vec, SizeIs(Lt(2)) for: { } size matches is less than 2
@@ -2049,6 +2106,8 @@ Xml.tests.cpp:<line number>: passed: encode( "[\x7F]" ) == "[\\x7F]" for: "[\x7F
Xml.tests.cpp:<line number>: passed: stream.str(), ContainsSubstring(R"(attr1="true")") && ContainsSubstring(R"(attr2="false")") for: "<?xml version="1.0" encoding="UTF-8"?> Xml.tests.cpp:<line number>: passed: stream.str(), ContainsSubstring(R"(attr1="true")") && ContainsSubstring(R"(attr2="false")") for: "<?xml version="1.0" encoding="UTF-8"?>
<Element1 attr1="true" attr2="false"/> <Element1 attr1="true" attr2="false"/>
" ( contains: "attr1="true"" and contains: "attr2="false"" ) " ( contains: "attr1="true"" and contains: "attr2="false"" )
Skip.tests.cpp:<line number>: passed:
Skip.tests.cpp:<line number>: skipped:
InternalBenchmark.tests.cpp:<line number>: passed: analysis.mean.point.count() == 23 for: 23.0 == 23 InternalBenchmark.tests.cpp:<line number>: passed: analysis.mean.point.count() == 23 for: 23.0 == 23
InternalBenchmark.tests.cpp:<line number>: passed: analysis.mean.lower_bound.count() == 23 for: 23.0 == 23 InternalBenchmark.tests.cpp:<line number>: passed: analysis.mean.lower_bound.count() == 23 for: 23.0 == 23
InternalBenchmark.tests.cpp:<line number>: passed: analysis.mean.upper_bound.count() == 23 for: 23.0 == 23 InternalBenchmark.tests.cpp:<line number>: passed: analysis.mean.upper_bound.count() == 23 for: 23.0 == 23
@@ -2138,6 +2197,9 @@ FloatingPoint.tests.cpp:<line number>: passed: convertToBits( -0. ) == ( 1ULL <<
9223372036854775808 (0x<hex digits>) 9223372036854775808 (0x<hex digits>)
FloatingPoint.tests.cpp:<line number>: passed: convertToBits( std::numeric_limits<float>::denorm_min() ) == 1 for: 1 == 1 FloatingPoint.tests.cpp:<line number>: passed: convertToBits( std::numeric_limits<float>::denorm_min() ) == 1 for: 1 == 1
FloatingPoint.tests.cpp:<line number>: passed: convertToBits( std::numeric_limits<double>::denorm_min() ) == 1 for: 1 == 1 FloatingPoint.tests.cpp:<line number>: passed: convertToBits( std::numeric_limits<double>::denorm_min() ) == 1 for: 1 == 1
Skip.tests.cpp:<line number>: skipped: 'skipping because answer = 41'
Skip.tests.cpp:<line number>: passed:
Skip.tests.cpp:<line number>: skipped: 'skipping because answer = 43'
Tag.tests.cpp:<line number>: passed: Catch::TestCaseInfo("", { "test with an empty tag", "[]" }, dummySourceLineInfo) Tag.tests.cpp:<line number>: passed: Catch::TestCaseInfo("", { "test with an empty tag", "[]" }, dummySourceLineInfo)
InternalBenchmark.tests.cpp:<line number>: passed: erfc_inv(1.103560) == Approx(-0.09203687623843015) for: -0.0920368762 == Approx( -0.0920368762 ) InternalBenchmark.tests.cpp:<line number>: passed: erfc_inv(1.103560) == Approx(-0.09203687623843015) for: -0.0920368762 == Approx( -0.0920368762 )
InternalBenchmark.tests.cpp:<line number>: passed: erfc_inv(1.067400) == Approx(-0.05980291115763361) for: -0.0598029112 == Approx( -0.0598029112 ) InternalBenchmark.tests.cpp:<line number>: passed: erfc_inv(1.067400) == Approx(-0.05980291115763361) for: -0.0598029112 == Approx( -0.0598029112 )
@@ -2147,6 +2209,14 @@ InternalBenchmark.tests.cpp:<line number>: passed: res.outliers.total() == 0 for
Misc.tests.cpp:<line number>: passed: Misc.tests.cpp:<line number>: passed:
Misc.tests.cpp:<line number>: passed: Misc.tests.cpp:<line number>: passed:
Misc.tests.cpp:<line number>: passed: Misc.tests.cpp:<line number>: passed:
Skip.tests.cpp:<line number>: failed: 3 == 4
Skip.tests.cpp:<line number>: skipped:
Skip.tests.cpp:<line number>: failed: explicitly
Skip.tests.cpp:<line number>: skipped:
Skip.tests.cpp:<line number>: failed: explicitly
Skip.tests.cpp:<line number>: skipped:
Skip.tests.cpp:<line number>: skipped:
Skip.tests.cpp:<line number>: failed: explicitly
Clara.tests.cpp:<line number>: passed: with 1 message: 'Catch::Clara::Detail::is_unary_function<decltype(unary1)>::value' Clara.tests.cpp:<line number>: passed: with 1 message: 'Catch::Clara::Detail::is_unary_function<decltype(unary1)>::value'
Clara.tests.cpp:<line number>: passed: with 1 message: 'Catch::Clara::Detail::is_unary_function<decltype(unary2)>::value' Clara.tests.cpp:<line number>: passed: with 1 message: 'Catch::Clara::Detail::is_unary_function<decltype(unary2)>::value'
Clara.tests.cpp:<line number>: passed: with 1 message: 'Catch::Clara::Detail::is_unary_function<decltype(unary3)>::value' Clara.tests.cpp:<line number>: passed: with 1 message: 'Catch::Clara::Detail::is_unary_function<decltype(unary3)>::value'
@@ -2203,6 +2273,7 @@ Misc.tests.cpp:<line number>: passed: a < b for: 1 < 2
Misc.tests.cpp:<line number>: passed: a != b for: 1 != 2 Misc.tests.cpp:<line number>: passed: a != b for: 1 != 2
Misc.tests.cpp:<line number>: passed: b != a for: 2 != 1 Misc.tests.cpp:<line number>: passed: b != a for: 2 != 1
Misc.tests.cpp:<line number>: passed: a != b for: 1 != 2 Misc.tests.cpp:<line number>: passed: a != b for: 1 != 2
Skip.tests.cpp:<line number>: skipped:
Tricky.tests.cpp:<line number>: passed: s == "7" for: "7" == "7" Tricky.tests.cpp:<line number>: passed: s == "7" for: "7" == "7"
Tricky.tests.cpp:<line number>: passed: ti == typeid(int) for: {?} == {?} Tricky.tests.cpp:<line number>: passed: ti == typeid(int) for: {?} == {?}
InternalBenchmark.tests.cpp:<line number>: passed: normal_cdf(0.000000) == Approx(0.50000000000000000) for: 0.5 == Approx( 0.5 ) InternalBenchmark.tests.cpp:<line number>: passed: normal_cdf(0.000000) == Approx(0.50000000000000000) for: 0.5 == Approx( 0.5 )
@@ -2287,9 +2358,13 @@ InternalBenchmark.tests.cpp:<line number>: passed: x >= old_x for: 128 >= 64
InternalBenchmark.tests.cpp:<line number>: passed: Timing.elapsed >= time for: 128 ns >= 100 ns InternalBenchmark.tests.cpp:<line number>: passed: Timing.elapsed >= time for: 128 ns >= 100 ns
InternalBenchmark.tests.cpp:<line number>: passed: Timing.result == Timing.iterations + 17 for: 145 == 145 InternalBenchmark.tests.cpp:<line number>: passed: Timing.result == Timing.iterations + 17 for: 145 == 145
InternalBenchmark.tests.cpp:<line number>: passed: Timing.iterations >= time.count() for: 128 >= 100 InternalBenchmark.tests.cpp:<line number>: passed: Timing.iterations >= time.count() for: 128 >= 100
Skip.tests.cpp:<line number>: passed:
Skip.tests.cpp:<line number>: skipped:
Skip.tests.cpp:<line number>: passed:
Misc.tests.cpp:<line number>: failed: false with 1 message: '3' Misc.tests.cpp:<line number>: failed: false with 1 message: '3'
Message.tests.cpp:<line number>: failed: false with 2 messages: 'hi' and 'i := 7' Message.tests.cpp:<line number>: failed: false with 2 messages: 'hi' and 'i := 7'
Tag.tests.cpp:<line number>: passed: testcase.tags, VectorContains( Tag( "magic-tag" ) ) && VectorContains( Tag( "."_catch_sr ) ) for: { {?}, {?} } ( Contains: {?} and Contains: {?} ) Tag.tests.cpp:<line number>: passed: testcase.tags, VectorContains( Tag( "magic-tag" ) ) && VectorContains( Tag( "."_catch_sr ) ) for: { {?}, {?} } ( Contains: {?} and Contains: {?} )
Skip.tests.cpp:<line number>: skipped: 'skipping because answer = 43'
StringManip.tests.cpp:<line number>: passed: splitStringRef("", ','), Equals(std::vector<StringRef>()) for: { } Equals: { } StringManip.tests.cpp:<line number>: passed: splitStringRef("", ','), Equals(std::vector<StringRef>()) for: { } Equals: { }
StringManip.tests.cpp:<line number>: passed: splitStringRef("abc", ','), Equals(std::vector<StringRef>{"abc"}) for: { abc } Equals: { abc } StringManip.tests.cpp:<line number>: passed: splitStringRef("abc", ','), Equals(std::vector<StringRef>{"abc"}) for: { abc } Equals: { abc }
StringManip.tests.cpp:<line number>: passed: splitStringRef("abc,def", ','), Equals(std::vector<StringRef>{"abc", "def"}) for: { abc, def } Equals: { abc, def } StringManip.tests.cpp:<line number>: passed: splitStringRef("abc,def", ','), Equals(std::vector<StringRef>{"abc", "def"}) for: { abc, def } Equals: { abc, def }
@@ -2355,6 +2430,7 @@ Generators.tests.cpp:<line number>: passed: strlen(std::get<0>(data)) == static_
Generators.tests.cpp:<line number>: passed: strlen(std::get<0>(data)) == static_cast<size_t>(std::get<1>(data)) for: 6 == 6 Generators.tests.cpp:<line number>: passed: strlen(std::get<0>(data)) == static_cast<size_t>(std::get<1>(data)) for: 6 == 6
Tag.tests.cpp:<line number>: passed: testcase.tags.size() == 1 for: 1 == 1 Tag.tests.cpp:<line number>: passed: testcase.tags.size() == 1 for: 1 == 1
Tag.tests.cpp:<line number>: passed: testcase.tags[0].original == "magic.tag"_catch_sr for: magic.tag == magic.tag Tag.tests.cpp:<line number>: passed: testcase.tags[0].original == "magic.tag"_catch_sr for: magic.tag == magic.tag
Skip.tests.cpp:<line number>: skipped:
Exception.tests.cpp:<line number>: failed: unexpected exception with message: 'Why would you throw a std::string?' Exception.tests.cpp:<line number>: failed: unexpected exception with message: 'Why would you throw a std::string?'
Misc.tests.cpp:<line number>: passed: result == "\"wide load\"" for: ""wide load"" == ""wide load"" Misc.tests.cpp:<line number>: passed: result == "\"wide load\"" for: ""wide load"" == ""wide load""
Misc.tests.cpp:<line number>: passed: result == "\"wide load\"" for: ""wide load"" == ""wide load"" Misc.tests.cpp:<line number>: passed: result == "\"wide load\"" for: ""wide load"" == ""wide load""
@@ -2451,7 +2527,7 @@ InternalBenchmark.tests.cpp:<line number>: passed: med == 18. for: 18.0 == 18.0
InternalBenchmark.tests.cpp:<line number>: passed: q3 == 23. for: 23.0 == 23.0 InternalBenchmark.tests.cpp:<line number>: passed: q3 == 23. for: 23.0 == 23.0
Misc.tests.cpp:<line number>: passed: Misc.tests.cpp:<line number>: passed:
Misc.tests.cpp:<line number>: passed: Misc.tests.cpp:<line number>: passed:
test cases: 394 | 304 passed | 83 failed | 7 failed as expected test cases: 409 | 309 passed | 84 failed | 5 skipped | 11 failed as expected
assertions: 2159 | 1989 passed | 143 failed | 27 failed as expected assertions: 2226 | 2049 passed | 145 failed | 32 failed as expected

View File

@@ -27,6 +27,16 @@ Tricky.tests.cpp:<line number>: FAILED:
explicitly with message: explicitly with message:
1514 1514
-------------------------------------------------------------------------------
#2615 - Throwing in constructor generator fails test case but does not abort
-------------------------------------------------------------------------------
Generators.tests.cpp:<line number>
...............................................................................
Generators.tests.cpp:<line number>: FAILED:
due to unexpected exception with message:
failure to init
------------------------------------------------------------------------------- -------------------------------------------------------------------------------
#748 - captures with unexpected exceptions #748 - captures with unexpected exceptions
outside assertions outside assertions
@@ -1164,6 +1174,14 @@ Exception.tests.cpp:<line number>: FAILED:
due to unexpected exception with message: due to unexpected exception with message:
unexpected exception unexpected exception
-------------------------------------------------------------------------------
a succeeding test can still be skipped
-------------------------------------------------------------------------------
Skip.tests.cpp:<line number>
...............................................................................
Skip.tests.cpp:<line number>: SKIPPED:
------------------------------------------------------------------------------- -------------------------------------------------------------------------------
checkedElse, failing checkedElse, failing
------------------------------------------------------------------------------- -------------------------------------------------------------------------------
@@ -1186,6 +1204,87 @@ Misc.tests.cpp:<line number>: FAILED:
with expansion: with expansion:
false false
-------------------------------------------------------------------------------
dynamic skipping works with generators
-------------------------------------------------------------------------------
Skip.tests.cpp:<line number>
...............................................................................
Skip.tests.cpp:<line number>: SKIPPED:
explicitly with message:
skipping because answer = 41
-------------------------------------------------------------------------------
dynamic skipping works with generators
-------------------------------------------------------------------------------
Skip.tests.cpp:<line number>
...............................................................................
Skip.tests.cpp:<line number>: SKIPPED:
explicitly with message:
skipping because answer = 43
-------------------------------------------------------------------------------
failed assertions before SKIP cause test case to fail
-------------------------------------------------------------------------------
Skip.tests.cpp:<line number>
...............................................................................
Skip.tests.cpp:<line number>: FAILED:
CHECK( 3 == 4 )
Skip.tests.cpp:<line number>: SKIPPED:
-------------------------------------------------------------------------------
failing for some generator values causes entire test case to fail
-------------------------------------------------------------------------------
Skip.tests.cpp:<line number>
...............................................................................
Skip.tests.cpp:<line number>: FAILED:
-------------------------------------------------------------------------------
failing for some generator values causes entire test case to fail
-------------------------------------------------------------------------------
Skip.tests.cpp:<line number>
...............................................................................
Skip.tests.cpp:<line number>: SKIPPED:
-------------------------------------------------------------------------------
failing for some generator values causes entire test case to fail
-------------------------------------------------------------------------------
Skip.tests.cpp:<line number>
...............................................................................
Skip.tests.cpp:<line number>: FAILED:
-------------------------------------------------------------------------------
failing for some generator values causes entire test case to fail
-------------------------------------------------------------------------------
Skip.tests.cpp:<line number>
...............................................................................
Skip.tests.cpp:<line number>: SKIPPED:
-------------------------------------------------------------------------------
failing in some unskipped sections causes entire test case to fail
skipped
-------------------------------------------------------------------------------
Skip.tests.cpp:<line number>
...............................................................................
Skip.tests.cpp:<line number>: SKIPPED:
-------------------------------------------------------------------------------
failing in some unskipped sections causes entire test case to fail
not skipped
-------------------------------------------------------------------------------
Skip.tests.cpp:<line number>
...............................................................................
Skip.tests.cpp:<line number>: FAILED:
loose text artifact loose text artifact
------------------------------------------------------------------------------- -------------------------------------------------------------------------------
just failure just failure
@@ -1304,6 +1403,19 @@ Misc.tests.cpp:<line number>: FAILED:
with expansion: with expansion:
1 == 2 1 == 2
a!
b1!
-------------------------------------------------------------------------------
nested sections can be skipped dynamically at runtime
B
B2
-------------------------------------------------------------------------------
Skip.tests.cpp:<line number>
...............................................................................
Skip.tests.cpp:<line number>: SKIPPED:
!
------------------------------------------------------------------------------- -------------------------------------------------------------------------------
not prints unscoped info from previous failures not prints unscoped info from previous failures
------------------------------------------------------------------------------- -------------------------------------------------------------------------------
@@ -1338,6 +1450,15 @@ Message.tests.cpp:<line number>: FAILED:
with message: with message:
this SHOULD be seen only ONCE this SHOULD be seen only ONCE
-------------------------------------------------------------------------------
sections can be skipped dynamically at runtime
skipped
-------------------------------------------------------------------------------
Skip.tests.cpp:<line number>
...............................................................................
Skip.tests.cpp:<line number>: SKIPPED:
------------------------------------------------------------------------------- -------------------------------------------------------------------------------
send a single char to INFO send a single char to INFO
------------------------------------------------------------------------------- -------------------------------------------------------------------------------
@@ -1361,6 +1482,16 @@ with messages:
hi hi
i := 7 i := 7
-------------------------------------------------------------------------------
skipped tests can optionally provide a reason
-------------------------------------------------------------------------------
Skip.tests.cpp:<line number>
...............................................................................
Skip.tests.cpp:<line number>: SKIPPED:
explicitly with message:
skipping because answer = 43
------------------------------------------------------------------------------- -------------------------------------------------------------------------------
stacks unscoped info in loops stacks unscoped info in loops
------------------------------------------------------------------------------- -------------------------------------------------------------------------------
@@ -1383,6 +1514,14 @@ with messages:
5 5
6 6
-------------------------------------------------------------------------------
tests can be skipped dynamically at runtime
-------------------------------------------------------------------------------
Skip.tests.cpp:<line number>
...............................................................................
Skip.tests.cpp:<line number>: SKIPPED:
------------------------------------------------------------------------------- -------------------------------------------------------------------------------
thrown std::strings are translated thrown std::strings are translated
------------------------------------------------------------------------------- -------------------------------------------------------------------------------
@@ -1394,6 +1533,6 @@ due to unexpected exception with message:
Why would you throw a std::string? Why would you throw a std::string?
=============================================================================== ===============================================================================
test cases: 394 | 318 passed | 69 failed | 7 failed as expected test cases: 409 | 323 passed | 69 failed | 6 skipped | 11 failed as expected
assertions: 2144 | 1989 passed | 128 failed | 27 failed as expected assertions: 2209 | 2049 passed | 128 failed | 32 failed as expected

View File

@@ -761,6 +761,16 @@ with expansion:
0.0f not is within 1 ULPs of -1.40129846e-45f ([-2.80259693e-45, -0. 0.0f not is within 1 ULPs of -1.40129846e-45f ([-2.80259693e-45, -0.
00000000e+00]) 00000000e+00])
-------------------------------------------------------------------------------
#2615 - Throwing in constructor generator fails test case but does not abort
-------------------------------------------------------------------------------
Generators.tests.cpp:<line number>
...............................................................................
Generators.tests.cpp:<line number>: FAILED:
due to unexpected exception with message:
failure to init
------------------------------------------------------------------------------- -------------------------------------------------------------------------------
#748 - captures with unexpected exceptions #748 - captures with unexpected exceptions
outside assertions outside assertions
@@ -4282,6 +4292,32 @@ Matchers.tests.cpp:<line number>: PASSED:
with expansion: with expansion:
SpecialException::what special exception has value of 2 SpecialException::what special exception has value of 2
-------------------------------------------------------------------------------
Exception message can be matched
-------------------------------------------------------------------------------
Matchers.tests.cpp:<line number>
...............................................................................
Matchers.tests.cpp:<line number>: PASSED:
REQUIRE_THROWS_MATCHES( throwsDerivedException(), DerivedException, MessageMatches( StartsWith( "Derived" ) ) )
with expansion:
DerivedException::what matches "starts with: "Derived""
Matchers.tests.cpp:<line number>: PASSED:
REQUIRE_THROWS_MATCHES( throwsDerivedException(), DerivedException, MessageMatches( EndsWith( "::what" ) ) )
with expansion:
DerivedException::what matches "ends with: "::what""
Matchers.tests.cpp:<line number>: PASSED:
REQUIRE_THROWS_MATCHES( throwsDerivedException(), DerivedException, MessageMatches( !StartsWith( "::what" ) ) )
with expansion:
DerivedException::what matches "not starts with: "::what""
Matchers.tests.cpp:<line number>: PASSED:
REQUIRE_THROWS_MATCHES( throwsSpecialException( 2 ), SpecialException, MessageMatches( StartsWith( "Special" ) ) )
with expansion:
SpecialException::what matches "starts with: "Special""
------------------------------------------------------------------------------- -------------------------------------------------------------------------------
Exception messages can be tested for Exception messages can be tested for
exact match exact match
@@ -4441,6 +4477,15 @@ Misc.tests.cpp:<line number>: PASSED:
with expansion: with expansion:
3628800 (0x<hex digits>) == 3628800 (0x<hex digits>) 3628800 (0x<hex digits>) == 3628800 (0x<hex digits>)
-------------------------------------------------------------------------------
Filter generator throws exception for empty generator
-------------------------------------------------------------------------------
GeneratorsImpl.tests.cpp:<line number>
...............................................................................
GeneratorsImpl.tests.cpp:<line number>: PASSED:
REQUIRE_THROWS_AS( filter( []( int ) { return false; }, value( 3 ) ), Catch::GeneratorException )
------------------------------------------------------------------------------- -------------------------------------------------------------------------------
Floating point matchers: double Floating point matchers: double
Relative Relative
@@ -4626,6 +4671,18 @@ Matchers.tests.cpp:<line number>: PASSED:
Matchers.tests.cpp:<line number>: PASSED: Matchers.tests.cpp:<line number>: PASSED:
REQUIRE_THROWS_AS( WithinRel( 1., 1. ), std::domain_error ) REQUIRE_THROWS_AS( WithinRel( 1., 1. ), std::domain_error )
-------------------------------------------------------------------------------
Floating point matchers: double
IsNaN
-------------------------------------------------------------------------------
Matchers.tests.cpp:<line number>
...............................................................................
Matchers.tests.cpp:<line number>: PASSED:
REQUIRE_THAT( 1., !IsNaN() )
with expansion:
1.0 not is NaN
------------------------------------------------------------------------------- -------------------------------------------------------------------------------
Floating point matchers: float Floating point matchers: float
Relative Relative
@@ -4819,6 +4876,18 @@ Matchers.tests.cpp:<line number>: PASSED:
Matchers.tests.cpp:<line number>: PASSED: Matchers.tests.cpp:<line number>: PASSED:
REQUIRE_THROWS_AS( WithinRel( 1.f, 1.f ), std::domain_error ) REQUIRE_THROWS_AS( WithinRel( 1.f, 1.f ), std::domain_error )
-------------------------------------------------------------------------------
Floating point matchers: float
IsNaN
-------------------------------------------------------------------------------
Matchers.tests.cpp:<line number>
...............................................................................
Matchers.tests.cpp:<line number>: PASSED:
REQUIRE_THAT( 1., !IsNaN() )
with expansion:
1.0 not is NaN
------------------------------------------------------------------------------- -------------------------------------------------------------------------------
Generators -- adapters Generators -- adapters
Filtering by predicate Filtering by predicate
@@ -13072,6 +13141,154 @@ with expansion:
== ==
There is no extra whitespace here There is no extra whitespace here
-------------------------------------------------------------------------------
Type conversions of RangeEquals and similar
Container conversions
Two equal containers of different container types
-------------------------------------------------------------------------------
MatchersRanges.tests.cpp:<line number>
...............................................................................
MatchersRanges.tests.cpp:<line number>: PASSED:
CHECK_THAT( array_int_a, RangeEquals( c_array ) )
with expansion:
{ 1, 2, 3 } elements are { 1, 2, 3 }
MatchersRanges.tests.cpp:<line number>: PASSED:
CHECK_THAT( array_int_a, UnorderedRangeEquals( c_array ) )
with expansion:
{ 1, 2, 3 } unordered elements are { 1, 2, 3 }
-------------------------------------------------------------------------------
Type conversions of RangeEquals and similar
Container conversions
Two equal containers of different container types (differ in array N)
-------------------------------------------------------------------------------
MatchersRanges.tests.cpp:<line number>
...............................................................................
MatchersRanges.tests.cpp:<line number>: PASSED:
CHECK_THAT( array_int_3, !RangeEquals( array_int_4 ) )
with expansion:
{ 1, 2, 3 } not elements are { 1, 2, 3, 4 }
MatchersRanges.tests.cpp:<line number>: PASSED:
CHECK_THAT( array_int_3, !UnorderedRangeEquals( array_int_4 ) )
with expansion:
{ 1, 2, 3 } not unordered elements are { 1, 2, 3, 4 }
-------------------------------------------------------------------------------
Type conversions of RangeEquals and similar
Container conversions
Two equal containers of different container types and value types
-------------------------------------------------------------------------------
MatchersRanges.tests.cpp:<line number>
...............................................................................
MatchersRanges.tests.cpp:<line number>: PASSED:
CHECK_THAT( array_int_a, RangeEquals( vector_char_a ) )
with expansion:
{ 1, 2, 3 } elements are { 1, 2, 3 }
MatchersRanges.tests.cpp:<line number>: PASSED:
CHECK_THAT( array_int_a, UnorderedRangeEquals( vector_char_a ) )
with expansion:
{ 1, 2, 3 } unordered elements are { 1, 2, 3 }
-------------------------------------------------------------------------------
Type conversions of RangeEquals and similar
Container conversions
Two equal containers, one random access, one not
-------------------------------------------------------------------------------
MatchersRanges.tests.cpp:<line number>
...............................................................................
MatchersRanges.tests.cpp:<line number>: PASSED:
with message:
ContainerIsRandomAccess( array_int_a ) != ContainerIsRandomAccess(
list_char_a )
MatchersRanges.tests.cpp:<line number>: PASSED:
CHECK_THAT( array_int_a, RangeEquals( list_char_a ) )
with expansion:
{ 1, 2, 3 } elements are { 1, 2, 3 }
MatchersRanges.tests.cpp:<line number>: PASSED:
CHECK_THAT( array_int_a, UnorderedRangeEquals( list_char_a ) )
with expansion:
{ 1, 2, 3 } unordered elements are { 1, 2, 3 }
-------------------------------------------------------------------------------
Type conversions of RangeEquals and similar
Value type
Two equal containers of different value types
-------------------------------------------------------------------------------
MatchersRanges.tests.cpp:<line number>
...............................................................................
MatchersRanges.tests.cpp:<line number>: PASSED:
CHECK_THAT( vector_int_a, RangeEquals( vector_char_a ) )
with expansion:
{ 1, 2, 3 } elements are { 1, 2, 3 }
MatchersRanges.tests.cpp:<line number>: PASSED:
CHECK_THAT( vector_int_a, UnorderedRangeEquals( vector_char_a ) )
with expansion:
{ 1, 2, 3 } unordered elements are { 1, 2, 3 }
-------------------------------------------------------------------------------
Type conversions of RangeEquals and similar
Value type
Two non-equal containers of different value types
-------------------------------------------------------------------------------
MatchersRanges.tests.cpp:<line number>
...............................................................................
MatchersRanges.tests.cpp:<line number>: PASSED:
CHECK_THAT( vector_int_a, !RangeEquals( vector_char_b ) )
with expansion:
{ 1, 2, 3 } not elements are { 1, 2, 2 }
MatchersRanges.tests.cpp:<line number>: PASSED:
CHECK_THAT( vector_int_a, !UnorderedRangeEquals( vector_char_b ) )
with expansion:
{ 1, 2, 3 } not unordered elements are { 1, 2, 2 }
-------------------------------------------------------------------------------
Type conversions of RangeEquals and similar
Ranges with begin that needs ADL
-------------------------------------------------------------------------------
MatchersRanges.tests.cpp:<line number>
...............................................................................
MatchersRanges.tests.cpp:<line number>: PASSED:
REQUIRE_THAT( a, !RangeEquals( b ) )
with expansion:
{ 1, 2, 3 } not elements are { 3, 2, 1 }
MatchersRanges.tests.cpp:<line number>: PASSED:
REQUIRE_THAT( a, UnorderedRangeEquals( b ) )
with expansion:
{ 1, 2, 3 } unordered elements are { 3, 2, 1 }
-------------------------------------------------------------------------------
Type conversions of RangeEquals and similar
Custom predicate
Two equal non-empty containers (close enough)
-------------------------------------------------------------------------------
MatchersRanges.tests.cpp:<line number>
...............................................................................
MatchersRanges.tests.cpp:<line number>: PASSED:
CHECK_THAT( vector_a, RangeEquals( array_a_plus_1, close_enough ) )
with expansion:
{ 1, 2, 3 } elements are { 2, 3, 4 }
MatchersRanges.tests.cpp:<line number>: PASSED:
CHECK_THAT( vector_a, UnorderedRangeEquals( array_a_plus_1, close_enough ) )
with expansion:
{ 1, 2, 3 } unordered elements are { 2, 3, 4 }
------------------------------------------------------------------------------- -------------------------------------------------------------------------------
Unexpected exceptions can be translated Unexpected exceptions can be translated
------------------------------------------------------------------------------- -------------------------------------------------------------------------------
@@ -13931,6 +14148,324 @@ MatchersRanges.tests.cpp:<line number>: PASSED:
with expansion: with expansion:
!false !false
-------------------------------------------------------------------------------
Usage of RangeEquals range matcher
Basic usage
Empty container matches empty container
-------------------------------------------------------------------------------
MatchersRanges.tests.cpp:<line number>
...............................................................................
MatchersRanges.tests.cpp:<line number>: PASSED:
CHECK_THAT( empty_vector, RangeEquals( empty_vector ) )
with expansion:
{ } elements are { }
-------------------------------------------------------------------------------
Usage of RangeEquals range matcher
Basic usage
Empty container does not match non-empty container
-------------------------------------------------------------------------------
MatchersRanges.tests.cpp:<line number>
...............................................................................
MatchersRanges.tests.cpp:<line number>: PASSED:
CHECK_THAT( empty_vector, !RangeEquals( non_empty_vector ) )
with expansion:
{ } not elements are { 1 }
MatchersRanges.tests.cpp:<line number>: PASSED:
CHECK_THAT( non_empty_vector, !RangeEquals( empty_vector ) )
with expansion:
{ 1 } not elements are { }
-------------------------------------------------------------------------------
Usage of RangeEquals range matcher
Basic usage
Two equal 1-length non-empty containers
-------------------------------------------------------------------------------
MatchersRanges.tests.cpp:<line number>
...............................................................................
MatchersRanges.tests.cpp:<line number>: PASSED:
CHECK_THAT( non_empty_array, RangeEquals( non_empty_array ) )
with expansion:
{ 1 } elements are { 1 }
-------------------------------------------------------------------------------
Usage of RangeEquals range matcher
Basic usage
Two equal-sized, equal, non-empty containers
-------------------------------------------------------------------------------
MatchersRanges.tests.cpp:<line number>
...............................................................................
MatchersRanges.tests.cpp:<line number>: PASSED:
CHECK_THAT( array_a, RangeEquals( array_a ) )
with expansion:
{ 1, 2, 3 } elements are { 1, 2, 3 }
-------------------------------------------------------------------------------
Usage of RangeEquals range matcher
Basic usage
Two equal-sized, non-equal, non-empty containers
-------------------------------------------------------------------------------
MatchersRanges.tests.cpp:<line number>
...............................................................................
MatchersRanges.tests.cpp:<line number>: PASSED:
CHECK_THAT( array_a, !RangeEquals( array_b ) )
with expansion:
{ 1, 2, 3 } not elements are { 2, 2, 3 }
MatchersRanges.tests.cpp:<line number>: PASSED:
CHECK_THAT( array_a, !RangeEquals( array_c ) )
with expansion:
{ 1, 2, 3 } not elements are { 1, 2, 2 }
-------------------------------------------------------------------------------
Usage of RangeEquals range matcher
Basic usage
Two non-equal-sized, non-empty containers (with same first elements)
-------------------------------------------------------------------------------
MatchersRanges.tests.cpp:<line number>
...............................................................................
MatchersRanges.tests.cpp:<line number>: PASSED:
CHECK_THAT( vector_a, !RangeEquals( vector_b ) )
with expansion:
{ 1, 2, 3 } not elements are { 1, 2, 3, 4 }
-------------------------------------------------------------------------------
Usage of RangeEquals range matcher
Custom predicate
Two equal non-empty containers (close enough)
-------------------------------------------------------------------------------
MatchersRanges.tests.cpp:<line number>
...............................................................................
MatchersRanges.tests.cpp:<line number>: PASSED:
CHECK_THAT( vector_a, RangeEquals( vector_a_plus_1, close_enough ) )
with expansion:
{ 1, 2, 3 } elements are { 2, 3, 4 }
-------------------------------------------------------------------------------
Usage of RangeEquals range matcher
Custom predicate
Two non-equal non-empty containers (close enough)
-------------------------------------------------------------------------------
MatchersRanges.tests.cpp:<line number>
...............................................................................
MatchersRanges.tests.cpp:<line number>: PASSED:
CHECK_THAT( vector_a, !RangeEquals( vector_b, close_enough ) )
with expansion:
{ 1, 2, 3 } not elements are { 3, 3, 4 }
-------------------------------------------------------------------------------
Usage of RangeEquals range matcher
Ranges that need ADL begin/end
-------------------------------------------------------------------------------
MatchersRanges.tests.cpp:<line number>
...............................................................................
MatchersRanges.tests.cpp:<line number>: PASSED:
REQUIRE_THAT( needs_adl1, RangeEquals( needs_adl2 ) )
with expansion:
{ 1, 2, 3, 4, 5 } elements are { 1, 2, 3, 4, 5 }
MatchersRanges.tests.cpp:<line number>: PASSED:
REQUIRE_THAT( needs_adl1, RangeEquals( needs_adl3, []( int l, int r ) { return l + 1 == r; } ) )
with expansion:
{ 1, 2, 3, 4, 5 } elements are { 2, 3, 4, 5, 6 }
-------------------------------------------------------------------------------
Usage of RangeEquals range matcher
Check short-circuiting behaviour
Check short-circuits on failure
-------------------------------------------------------------------------------
MatchersRanges.tests.cpp:<line number>
...............................................................................
MatchersRanges.tests.cpp:<line number>: PASSED:
REQUIRE_THAT( mocked1, !RangeEquals( arr ) )
with expansion:
{ 1, 2, 3, 4 } not elements are { 1, 2, 4, 4 }
MatchersRanges.tests.cpp:<line number>: PASSED:
REQUIRE( mocked1.m_derefed[0] )
with expansion:
true
MatchersRanges.tests.cpp:<line number>: PASSED:
REQUIRE( mocked1.m_derefed[1] )
with expansion:
true
MatchersRanges.tests.cpp:<line number>: PASSED:
REQUIRE( mocked1.m_derefed[2] )
with expansion:
true
MatchersRanges.tests.cpp:<line number>: PASSED:
REQUIRE_FALSE( mocked1.m_derefed[3] )
with expansion:
!false
-------------------------------------------------------------------------------
Usage of RangeEquals range matcher
Check short-circuiting behaviour
All elements are checked on success
-------------------------------------------------------------------------------
MatchersRanges.tests.cpp:<line number>
...............................................................................
MatchersRanges.tests.cpp:<line number>: PASSED:
REQUIRE_THAT( mocked1, RangeEquals( arr ) )
with expansion:
{ 1, 2, 3, 4 } elements are { 1, 2, 3, 4 }
MatchersRanges.tests.cpp:<line number>: PASSED:
REQUIRE( mocked1.m_derefed[0] )
with expansion:
true
MatchersRanges.tests.cpp:<line number>: PASSED:
REQUIRE( mocked1.m_derefed[1] )
with expansion:
true
MatchersRanges.tests.cpp:<line number>: PASSED:
REQUIRE( mocked1.m_derefed[2] )
with expansion:
true
MatchersRanges.tests.cpp:<line number>: PASSED:
REQUIRE( mocked1.m_derefed[3] )
with expansion:
true
-------------------------------------------------------------------------------
Usage of UnorderedRangeEquals range matcher
Basic usage
Empty container matches empty container
-------------------------------------------------------------------------------
MatchersRanges.tests.cpp:<line number>
...............................................................................
MatchersRanges.tests.cpp:<line number>: PASSED:
CHECK_THAT( empty_vector, UnorderedRangeEquals( empty_vector ) )
with expansion:
{ } unordered elements are { }
-------------------------------------------------------------------------------
Usage of UnorderedRangeEquals range matcher
Basic usage
Empty container does not match non-empty container
-------------------------------------------------------------------------------
MatchersRanges.tests.cpp:<line number>
...............................................................................
MatchersRanges.tests.cpp:<line number>: PASSED:
CHECK_THAT( empty_vector, !UnorderedRangeEquals( non_empty_vector ) )
with expansion:
{ } not unordered elements are { 1 }
MatchersRanges.tests.cpp:<line number>: PASSED:
CHECK_THAT( non_empty_vector, !UnorderedRangeEquals( empty_vector ) )
with expansion:
{ 1 } not unordered elements are { }
-------------------------------------------------------------------------------
Usage of UnorderedRangeEquals range matcher
Basic usage
Two equal 1-length non-empty containers
-------------------------------------------------------------------------------
MatchersRanges.tests.cpp:<line number>
...............................................................................
MatchersRanges.tests.cpp:<line number>: PASSED:
CHECK_THAT( non_empty_array, UnorderedRangeEquals( non_empty_array ) )
with expansion:
{ 1 } unordered elements are { 1 }
-------------------------------------------------------------------------------
Usage of UnorderedRangeEquals range matcher
Basic usage
Two equal-sized, equal, non-empty containers
-------------------------------------------------------------------------------
MatchersRanges.tests.cpp:<line number>
...............................................................................
MatchersRanges.tests.cpp:<line number>: PASSED:
CHECK_THAT( array_a, UnorderedRangeEquals( array_a ) )
with expansion:
{ 1, 2, 3 } unordered elements are { 1, 2, 3 }
-------------------------------------------------------------------------------
Usage of UnorderedRangeEquals range matcher
Basic usage
Two equal-sized, non-equal, non-empty containers
-------------------------------------------------------------------------------
MatchersRanges.tests.cpp:<line number>
...............................................................................
MatchersRanges.tests.cpp:<line number>: PASSED:
CHECK_THAT( array_a, !UnorderedRangeEquals( array_b ) )
with expansion:
{ 1, 2, 3 } not unordered elements are { 2, 2, 3 }
-------------------------------------------------------------------------------
Usage of UnorderedRangeEquals range matcher
Basic usage
Two non-equal-sized, non-empty containers
-------------------------------------------------------------------------------
MatchersRanges.tests.cpp:<line number>
...............................................................................
MatchersRanges.tests.cpp:<line number>: PASSED:
CHECK_THAT( vector_a, !UnorderedRangeEquals( vector_b ) )
with expansion:
{ 1, 2, 3 } not unordered elements are { 1, 2, 3, 4 }
-------------------------------------------------------------------------------
Usage of UnorderedRangeEquals range matcher
Custom predicate
Two equal non-empty containers (close enough)
-------------------------------------------------------------------------------
MatchersRanges.tests.cpp:<line number>
...............................................................................
MatchersRanges.tests.cpp:<line number>: PASSED:
CHECK_THAT( vector_a, UnorderedRangeEquals( vector_a_plus_1, close_enough ) )
with expansion:
{ 1, 10, 20 } unordered elements are { 11, 21, 2 }
-------------------------------------------------------------------------------
Usage of UnorderedRangeEquals range matcher
Custom predicate
Two non-equal non-empty containers (close enough)
-------------------------------------------------------------------------------
MatchersRanges.tests.cpp:<line number>
...............................................................................
MatchersRanges.tests.cpp:<line number>: PASSED:
CHECK_THAT( vector_a, !UnorderedRangeEquals( vector_b, close_enough ) )
with expansion:
{ 1, 10, 21 } not unordered elements are { 11, 21, 3 }
-------------------------------------------------------------------------------
Usage of UnorderedRangeEquals range matcher
Ranges that need ADL begin/end
-------------------------------------------------------------------------------
MatchersRanges.tests.cpp:<line number>
...............................................................................
MatchersRanges.tests.cpp:<line number>: PASSED:
REQUIRE_THAT( needs_adl1, UnorderedRangeEquals( needs_adl2 ) )
with expansion:
{ 1, 2, 3, 4, 5 } unordered elements are { 1, 2, 3, 4, 5 }
------------------------------------------------------------------------------- -------------------------------------------------------------------------------
Usage of the SizeIs range matcher Usage of the SizeIs range matcher
Some with stdlib containers Some with stdlib containers
@@ -14633,6 +15168,16 @@ with expansion:
<Element1 attr1="true" attr2="false"/> <Element1 attr1="true" attr2="false"/>
" ( contains: "attr1="true"" and contains: "attr2="false"" ) " ( contains: "attr1="true"" and contains: "attr2="false"" )
-------------------------------------------------------------------------------
a succeeding test can still be skipped
-------------------------------------------------------------------------------
Skip.tests.cpp:<line number>
...............................................................................
Skip.tests.cpp:<line number>: PASSED:
Skip.tests.cpp:<line number>: SKIPPED:
------------------------------------------------------------------------------- -------------------------------------------------------------------------------
analyse no analysis analyse no analysis
------------------------------------------------------------------------------- -------------------------------------------------------------------------------
@@ -15178,6 +15723,34 @@ FloatingPoint.tests.cpp:<line number>: PASSED:
with expansion: with expansion:
1 == 1 1 == 1
-------------------------------------------------------------------------------
dynamic skipping works with generators
-------------------------------------------------------------------------------
Skip.tests.cpp:<line number>
...............................................................................
Skip.tests.cpp:<line number>: SKIPPED:
explicitly with message:
skipping because answer = 41
-------------------------------------------------------------------------------
dynamic skipping works with generators
-------------------------------------------------------------------------------
Skip.tests.cpp:<line number>
...............................................................................
Skip.tests.cpp:<line number>: PASSED:
-------------------------------------------------------------------------------
dynamic skipping works with generators
-------------------------------------------------------------------------------
Skip.tests.cpp:<line number>
...............................................................................
Skip.tests.cpp:<line number>: SKIPPED:
explicitly with message:
skipping because answer = 43
------------------------------------------------------------------------------- -------------------------------------------------------------------------------
empty tags are not allowed empty tags are not allowed
------------------------------------------------------------------------------- -------------------------------------------------------------------------------
@@ -15253,6 +15826,67 @@ Misc.tests.cpp:<line number>
Misc.tests.cpp:<line number>: PASSED: Misc.tests.cpp:<line number>: PASSED:
-------------------------------------------------------------------------------
failed assertions before SKIP cause test case to fail
-------------------------------------------------------------------------------
Skip.tests.cpp:<line number>
...............................................................................
Skip.tests.cpp:<line number>: FAILED:
CHECK( 3 == 4 )
Skip.tests.cpp:<line number>: SKIPPED:
-------------------------------------------------------------------------------
failing for some generator values causes entire test case to fail
-------------------------------------------------------------------------------
Skip.tests.cpp:<line number>
...............................................................................
Skip.tests.cpp:<line number>: FAILED:
-------------------------------------------------------------------------------
failing for some generator values causes entire test case to fail
-------------------------------------------------------------------------------
Skip.tests.cpp:<line number>
...............................................................................
Skip.tests.cpp:<line number>: SKIPPED:
-------------------------------------------------------------------------------
failing for some generator values causes entire test case to fail
-------------------------------------------------------------------------------
Skip.tests.cpp:<line number>
...............................................................................
Skip.tests.cpp:<line number>: FAILED:
-------------------------------------------------------------------------------
failing for some generator values causes entire test case to fail
-------------------------------------------------------------------------------
Skip.tests.cpp:<line number>
...............................................................................
Skip.tests.cpp:<line number>: SKIPPED:
-------------------------------------------------------------------------------
failing in some unskipped sections causes entire test case to fail
skipped
-------------------------------------------------------------------------------
Skip.tests.cpp:<line number>
...............................................................................
Skip.tests.cpp:<line number>: SKIPPED:
-------------------------------------------------------------------------------
failing in some unskipped sections causes entire test case to fail
not skipped
-------------------------------------------------------------------------------
Skip.tests.cpp:<line number>
...............................................................................
Skip.tests.cpp:<line number>: FAILED:
------------------------------------------------------------------------------- -------------------------------------------------------------------------------
first tag first tag
------------------------------------------------------------------------------- -------------------------------------------------------------------------------
@@ -15749,6 +16383,40 @@ Misc.tests.cpp:<line number>: PASSED:
with expansion: with expansion:
1 != 2 1 != 2
a-------------------------------------------------------------------------------
nested sections can be skipped dynamically at runtime
A
-------------------------------------------------------------------------------
Skip.tests.cpp:<line number>
...............................................................................
No assertions in section 'A'
!
b1-------------------------------------------------------------------------------
nested sections can be skipped dynamically at runtime
B
B1
-------------------------------------------------------------------------------
Skip.tests.cpp:<line number>
...............................................................................
No assertions in section 'B1'
!
-------------------------------------------------------------------------------
nested sections can be skipped dynamically at runtime
B
B2
-------------------------------------------------------------------------------
Skip.tests.cpp:<line number>
...............................................................................
Skip.tests.cpp:<line number>: SKIPPED:
!
------------------------------------------------------------------------------- -------------------------------------------------------------------------------
non streamable - with conv. op non streamable - with conv. op
------------------------------------------------------------------------------- -------------------------------------------------------------------------------
@@ -16350,6 +17018,33 @@ Misc.tests.cpp:<line number>
No assertions in test case 'second tag' No assertions in test case 'second tag'
-------------------------------------------------------------------------------
sections can be skipped dynamically at runtime
not skipped
-------------------------------------------------------------------------------
Skip.tests.cpp:<line number>
...............................................................................
Skip.tests.cpp:<line number>: PASSED:
-------------------------------------------------------------------------------
sections can be skipped dynamically at runtime
skipped
-------------------------------------------------------------------------------
Skip.tests.cpp:<line number>
...............................................................................
Skip.tests.cpp:<line number>: SKIPPED:
-------------------------------------------------------------------------------
sections can be skipped dynamically at runtime
also not skipped
-------------------------------------------------------------------------------
Skip.tests.cpp:<line number>
...............................................................................
Skip.tests.cpp:<line number>: PASSED:
------------------------------------------------------------------------------- -------------------------------------------------------------------------------
send a single char to INFO send a single char to INFO
------------------------------------------------------------------------------- -------------------------------------------------------------------------------
@@ -16384,6 +17079,16 @@ Tag.tests.cpp:<line number>: PASSED:
with expansion: with expansion:
{ {?}, {?} } ( Contains: {?} and Contains: {?} ) { {?}, {?} } ( Contains: {?} and Contains: {?} )
-------------------------------------------------------------------------------
skipped tests can optionally provide a reason
-------------------------------------------------------------------------------
Skip.tests.cpp:<line number>
...............................................................................
Skip.tests.cpp:<line number>: SKIPPED:
explicitly with message:
skipping because answer = 43
------------------------------------------------------------------------------- -------------------------------------------------------------------------------
splitString splitString
------------------------------------------------------------------------------- -------------------------------------------------------------------------------
@@ -16811,6 +17516,14 @@ Tag.tests.cpp:<line number>: PASSED:
with expansion: with expansion:
magic.tag == magic.tag magic.tag == magic.tag
-------------------------------------------------------------------------------
tests can be skipped dynamically at runtime
-------------------------------------------------------------------------------
Skip.tests.cpp:<line number>
...............................................................................
Skip.tests.cpp:<line number>: SKIPPED:
------------------------------------------------------------------------------- -------------------------------------------------------------------------------
thrown std::strings are translated thrown std::strings are translated
------------------------------------------------------------------------------- -------------------------------------------------------------------------------
@@ -17518,6 +18231,6 @@ Misc.tests.cpp:<line number>
Misc.tests.cpp:<line number>: PASSED: Misc.tests.cpp:<line number>: PASSED:
=============================================================================== ===============================================================================
test cases: 394 | 304 passed | 83 failed | 7 failed as expected test cases: 409 | 309 passed | 84 failed | 5 skipped | 11 failed as expected
assertions: 2159 | 1989 passed | 143 failed | 27 failed as expected assertions: 2226 | 2049 passed | 145 failed | 32 failed as expected

View File

@@ -759,6 +759,16 @@ with expansion:
0.0f not is within 1 ULPs of -1.40129846e-45f ([-2.80259693e-45, -0. 0.0f not is within 1 ULPs of -1.40129846e-45f ([-2.80259693e-45, -0.
00000000e+00]) 00000000e+00])
-------------------------------------------------------------------------------
#2615 - Throwing in constructor generator fails test case but does not abort
-------------------------------------------------------------------------------
Generators.tests.cpp:<line number>
...............................................................................
Generators.tests.cpp:<line number>: FAILED:
due to unexpected exception with message:
failure to init
------------------------------------------------------------------------------- -------------------------------------------------------------------------------
#748 - captures with unexpected exceptions #748 - captures with unexpected exceptions
outside assertions outside assertions
@@ -4280,6 +4290,32 @@ Matchers.tests.cpp:<line number>: PASSED:
with expansion: with expansion:
SpecialException::what special exception has value of 2 SpecialException::what special exception has value of 2
-------------------------------------------------------------------------------
Exception message can be matched
-------------------------------------------------------------------------------
Matchers.tests.cpp:<line number>
...............................................................................
Matchers.tests.cpp:<line number>: PASSED:
REQUIRE_THROWS_MATCHES( throwsDerivedException(), DerivedException, MessageMatches( StartsWith( "Derived" ) ) )
with expansion:
DerivedException::what matches "starts with: "Derived""
Matchers.tests.cpp:<line number>: PASSED:
REQUIRE_THROWS_MATCHES( throwsDerivedException(), DerivedException, MessageMatches( EndsWith( "::what" ) ) )
with expansion:
DerivedException::what matches "ends with: "::what""
Matchers.tests.cpp:<line number>: PASSED:
REQUIRE_THROWS_MATCHES( throwsDerivedException(), DerivedException, MessageMatches( !StartsWith( "::what" ) ) )
with expansion:
DerivedException::what matches "not starts with: "::what""
Matchers.tests.cpp:<line number>: PASSED:
REQUIRE_THROWS_MATCHES( throwsSpecialException( 2 ), SpecialException, MessageMatches( StartsWith( "Special" ) ) )
with expansion:
SpecialException::what matches "starts with: "Special""
------------------------------------------------------------------------------- -------------------------------------------------------------------------------
Exception messages can be tested for Exception messages can be tested for
exact match exact match
@@ -4439,6 +4475,15 @@ Misc.tests.cpp:<line number>: PASSED:
with expansion: with expansion:
3628800 (0x<hex digits>) == 3628800 (0x<hex digits>) 3628800 (0x<hex digits>) == 3628800 (0x<hex digits>)
-------------------------------------------------------------------------------
Filter generator throws exception for empty generator
-------------------------------------------------------------------------------
GeneratorsImpl.tests.cpp:<line number>
...............................................................................
GeneratorsImpl.tests.cpp:<line number>: PASSED:
REQUIRE_THROWS_AS( filter( []( int ) { return false; }, value( 3 ) ), Catch::GeneratorException )
------------------------------------------------------------------------------- -------------------------------------------------------------------------------
Floating point matchers: double Floating point matchers: double
Relative Relative
@@ -4624,6 +4669,18 @@ Matchers.tests.cpp:<line number>: PASSED:
Matchers.tests.cpp:<line number>: PASSED: Matchers.tests.cpp:<line number>: PASSED:
REQUIRE_THROWS_AS( WithinRel( 1., 1. ), std::domain_error ) REQUIRE_THROWS_AS( WithinRel( 1., 1. ), std::domain_error )
-------------------------------------------------------------------------------
Floating point matchers: double
IsNaN
-------------------------------------------------------------------------------
Matchers.tests.cpp:<line number>
...............................................................................
Matchers.tests.cpp:<line number>: PASSED:
REQUIRE_THAT( 1., !IsNaN() )
with expansion:
1.0 not is NaN
------------------------------------------------------------------------------- -------------------------------------------------------------------------------
Floating point matchers: float Floating point matchers: float
Relative Relative
@@ -4817,6 +4874,18 @@ Matchers.tests.cpp:<line number>: PASSED:
Matchers.tests.cpp:<line number>: PASSED: Matchers.tests.cpp:<line number>: PASSED:
REQUIRE_THROWS_AS( WithinRel( 1.f, 1.f ), std::domain_error ) REQUIRE_THROWS_AS( WithinRel( 1.f, 1.f ), std::domain_error )
-------------------------------------------------------------------------------
Floating point matchers: float
IsNaN
-------------------------------------------------------------------------------
Matchers.tests.cpp:<line number>
...............................................................................
Matchers.tests.cpp:<line number>: PASSED:
REQUIRE_THAT( 1., !IsNaN() )
with expansion:
1.0 not is NaN
------------------------------------------------------------------------------- -------------------------------------------------------------------------------
Generators -- adapters Generators -- adapters
Filtering by predicate Filtering by predicate
@@ -13065,6 +13134,154 @@ with expansion:
== ==
There is no extra whitespace here There is no extra whitespace here
-------------------------------------------------------------------------------
Type conversions of RangeEquals and similar
Container conversions
Two equal containers of different container types
-------------------------------------------------------------------------------
MatchersRanges.tests.cpp:<line number>
...............................................................................
MatchersRanges.tests.cpp:<line number>: PASSED:
CHECK_THAT( array_int_a, RangeEquals( c_array ) )
with expansion:
{ 1, 2, 3 } elements are { 1, 2, 3 }
MatchersRanges.tests.cpp:<line number>: PASSED:
CHECK_THAT( array_int_a, UnorderedRangeEquals( c_array ) )
with expansion:
{ 1, 2, 3 } unordered elements are { 1, 2, 3 }
-------------------------------------------------------------------------------
Type conversions of RangeEquals and similar
Container conversions
Two equal containers of different container types (differ in array N)
-------------------------------------------------------------------------------
MatchersRanges.tests.cpp:<line number>
...............................................................................
MatchersRanges.tests.cpp:<line number>: PASSED:
CHECK_THAT( array_int_3, !RangeEquals( array_int_4 ) )
with expansion:
{ 1, 2, 3 } not elements are { 1, 2, 3, 4 }
MatchersRanges.tests.cpp:<line number>: PASSED:
CHECK_THAT( array_int_3, !UnorderedRangeEquals( array_int_4 ) )
with expansion:
{ 1, 2, 3 } not unordered elements are { 1, 2, 3, 4 }
-------------------------------------------------------------------------------
Type conversions of RangeEquals and similar
Container conversions
Two equal containers of different container types and value types
-------------------------------------------------------------------------------
MatchersRanges.tests.cpp:<line number>
...............................................................................
MatchersRanges.tests.cpp:<line number>: PASSED:
CHECK_THAT( array_int_a, RangeEquals( vector_char_a ) )
with expansion:
{ 1, 2, 3 } elements are { 1, 2, 3 }
MatchersRanges.tests.cpp:<line number>: PASSED:
CHECK_THAT( array_int_a, UnorderedRangeEquals( vector_char_a ) )
with expansion:
{ 1, 2, 3 } unordered elements are { 1, 2, 3 }
-------------------------------------------------------------------------------
Type conversions of RangeEquals and similar
Container conversions
Two equal containers, one random access, one not
-------------------------------------------------------------------------------
MatchersRanges.tests.cpp:<line number>
...............................................................................
MatchersRanges.tests.cpp:<line number>: PASSED:
with message:
ContainerIsRandomAccess( array_int_a ) != ContainerIsRandomAccess(
list_char_a )
MatchersRanges.tests.cpp:<line number>: PASSED:
CHECK_THAT( array_int_a, RangeEquals( list_char_a ) )
with expansion:
{ 1, 2, 3 } elements are { 1, 2, 3 }
MatchersRanges.tests.cpp:<line number>: PASSED:
CHECK_THAT( array_int_a, UnorderedRangeEquals( list_char_a ) )
with expansion:
{ 1, 2, 3 } unordered elements are { 1, 2, 3 }
-------------------------------------------------------------------------------
Type conversions of RangeEquals and similar
Value type
Two equal containers of different value types
-------------------------------------------------------------------------------
MatchersRanges.tests.cpp:<line number>
...............................................................................
MatchersRanges.tests.cpp:<line number>: PASSED:
CHECK_THAT( vector_int_a, RangeEquals( vector_char_a ) )
with expansion:
{ 1, 2, 3 } elements are { 1, 2, 3 }
MatchersRanges.tests.cpp:<line number>: PASSED:
CHECK_THAT( vector_int_a, UnorderedRangeEquals( vector_char_a ) )
with expansion:
{ 1, 2, 3 } unordered elements are { 1, 2, 3 }
-------------------------------------------------------------------------------
Type conversions of RangeEquals and similar
Value type
Two non-equal containers of different value types
-------------------------------------------------------------------------------
MatchersRanges.tests.cpp:<line number>
...............................................................................
MatchersRanges.tests.cpp:<line number>: PASSED:
CHECK_THAT( vector_int_a, !RangeEquals( vector_char_b ) )
with expansion:
{ 1, 2, 3 } not elements are { 1, 2, 2 }
MatchersRanges.tests.cpp:<line number>: PASSED:
CHECK_THAT( vector_int_a, !UnorderedRangeEquals( vector_char_b ) )
with expansion:
{ 1, 2, 3 } not unordered elements are { 1, 2, 2 }
-------------------------------------------------------------------------------
Type conversions of RangeEquals and similar
Ranges with begin that needs ADL
-------------------------------------------------------------------------------
MatchersRanges.tests.cpp:<line number>
...............................................................................
MatchersRanges.tests.cpp:<line number>: PASSED:
REQUIRE_THAT( a, !RangeEquals( b ) )
with expansion:
{ 1, 2, 3 } not elements are { 3, 2, 1 }
MatchersRanges.tests.cpp:<line number>: PASSED:
REQUIRE_THAT( a, UnorderedRangeEquals( b ) )
with expansion:
{ 1, 2, 3 } unordered elements are { 3, 2, 1 }
-------------------------------------------------------------------------------
Type conversions of RangeEquals and similar
Custom predicate
Two equal non-empty containers (close enough)
-------------------------------------------------------------------------------
MatchersRanges.tests.cpp:<line number>
...............................................................................
MatchersRanges.tests.cpp:<line number>: PASSED:
CHECK_THAT( vector_a, RangeEquals( array_a_plus_1, close_enough ) )
with expansion:
{ 1, 2, 3 } elements are { 2, 3, 4 }
MatchersRanges.tests.cpp:<line number>: PASSED:
CHECK_THAT( vector_a, UnorderedRangeEquals( array_a_plus_1, close_enough ) )
with expansion:
{ 1, 2, 3 } unordered elements are { 2, 3, 4 }
------------------------------------------------------------------------------- -------------------------------------------------------------------------------
Unexpected exceptions can be translated Unexpected exceptions can be translated
------------------------------------------------------------------------------- -------------------------------------------------------------------------------
@@ -13924,6 +14141,324 @@ MatchersRanges.tests.cpp:<line number>: PASSED:
with expansion: with expansion:
!false !false
-------------------------------------------------------------------------------
Usage of RangeEquals range matcher
Basic usage
Empty container matches empty container
-------------------------------------------------------------------------------
MatchersRanges.tests.cpp:<line number>
...............................................................................
MatchersRanges.tests.cpp:<line number>: PASSED:
CHECK_THAT( empty_vector, RangeEquals( empty_vector ) )
with expansion:
{ } elements are { }
-------------------------------------------------------------------------------
Usage of RangeEquals range matcher
Basic usage
Empty container does not match non-empty container
-------------------------------------------------------------------------------
MatchersRanges.tests.cpp:<line number>
...............................................................................
MatchersRanges.tests.cpp:<line number>: PASSED:
CHECK_THAT( empty_vector, !RangeEquals( non_empty_vector ) )
with expansion:
{ } not elements are { 1 }
MatchersRanges.tests.cpp:<line number>: PASSED:
CHECK_THAT( non_empty_vector, !RangeEquals( empty_vector ) )
with expansion:
{ 1 } not elements are { }
-------------------------------------------------------------------------------
Usage of RangeEquals range matcher
Basic usage
Two equal 1-length non-empty containers
-------------------------------------------------------------------------------
MatchersRanges.tests.cpp:<line number>
...............................................................................
MatchersRanges.tests.cpp:<line number>: PASSED:
CHECK_THAT( non_empty_array, RangeEquals( non_empty_array ) )
with expansion:
{ 1 } elements are { 1 }
-------------------------------------------------------------------------------
Usage of RangeEquals range matcher
Basic usage
Two equal-sized, equal, non-empty containers
-------------------------------------------------------------------------------
MatchersRanges.tests.cpp:<line number>
...............................................................................
MatchersRanges.tests.cpp:<line number>: PASSED:
CHECK_THAT( array_a, RangeEquals( array_a ) )
with expansion:
{ 1, 2, 3 } elements are { 1, 2, 3 }
-------------------------------------------------------------------------------
Usage of RangeEquals range matcher
Basic usage
Two equal-sized, non-equal, non-empty containers
-------------------------------------------------------------------------------
MatchersRanges.tests.cpp:<line number>
...............................................................................
MatchersRanges.tests.cpp:<line number>: PASSED:
CHECK_THAT( array_a, !RangeEquals( array_b ) )
with expansion:
{ 1, 2, 3 } not elements are { 2, 2, 3 }
MatchersRanges.tests.cpp:<line number>: PASSED:
CHECK_THAT( array_a, !RangeEquals( array_c ) )
with expansion:
{ 1, 2, 3 } not elements are { 1, 2, 2 }
-------------------------------------------------------------------------------
Usage of RangeEquals range matcher
Basic usage
Two non-equal-sized, non-empty containers (with same first elements)
-------------------------------------------------------------------------------
MatchersRanges.tests.cpp:<line number>
...............................................................................
MatchersRanges.tests.cpp:<line number>: PASSED:
CHECK_THAT( vector_a, !RangeEquals( vector_b ) )
with expansion:
{ 1, 2, 3 } not elements are { 1, 2, 3, 4 }
-------------------------------------------------------------------------------
Usage of RangeEquals range matcher
Custom predicate
Two equal non-empty containers (close enough)
-------------------------------------------------------------------------------
MatchersRanges.tests.cpp:<line number>
...............................................................................
MatchersRanges.tests.cpp:<line number>: PASSED:
CHECK_THAT( vector_a, RangeEquals( vector_a_plus_1, close_enough ) )
with expansion:
{ 1, 2, 3 } elements are { 2, 3, 4 }
-------------------------------------------------------------------------------
Usage of RangeEquals range matcher
Custom predicate
Two non-equal non-empty containers (close enough)
-------------------------------------------------------------------------------
MatchersRanges.tests.cpp:<line number>
...............................................................................
MatchersRanges.tests.cpp:<line number>: PASSED:
CHECK_THAT( vector_a, !RangeEquals( vector_b, close_enough ) )
with expansion:
{ 1, 2, 3 } not elements are { 3, 3, 4 }
-------------------------------------------------------------------------------
Usage of RangeEquals range matcher
Ranges that need ADL begin/end
-------------------------------------------------------------------------------
MatchersRanges.tests.cpp:<line number>
...............................................................................
MatchersRanges.tests.cpp:<line number>: PASSED:
REQUIRE_THAT( needs_adl1, RangeEquals( needs_adl2 ) )
with expansion:
{ 1, 2, 3, 4, 5 } elements are { 1, 2, 3, 4, 5 }
MatchersRanges.tests.cpp:<line number>: PASSED:
REQUIRE_THAT( needs_adl1, RangeEquals( needs_adl3, []( int l, int r ) { return l + 1 == r; } ) )
with expansion:
{ 1, 2, 3, 4, 5 } elements are { 2, 3, 4, 5, 6 }
-------------------------------------------------------------------------------
Usage of RangeEquals range matcher
Check short-circuiting behaviour
Check short-circuits on failure
-------------------------------------------------------------------------------
MatchersRanges.tests.cpp:<line number>
...............................................................................
MatchersRanges.tests.cpp:<line number>: PASSED:
REQUIRE_THAT( mocked1, !RangeEquals( arr ) )
with expansion:
{ 1, 2, 3, 4 } not elements are { 1, 2, 4, 4 }
MatchersRanges.tests.cpp:<line number>: PASSED:
REQUIRE( mocked1.m_derefed[0] )
with expansion:
true
MatchersRanges.tests.cpp:<line number>: PASSED:
REQUIRE( mocked1.m_derefed[1] )
with expansion:
true
MatchersRanges.tests.cpp:<line number>: PASSED:
REQUIRE( mocked1.m_derefed[2] )
with expansion:
true
MatchersRanges.tests.cpp:<line number>: PASSED:
REQUIRE_FALSE( mocked1.m_derefed[3] )
with expansion:
!false
-------------------------------------------------------------------------------
Usage of RangeEquals range matcher
Check short-circuiting behaviour
All elements are checked on success
-------------------------------------------------------------------------------
MatchersRanges.tests.cpp:<line number>
...............................................................................
MatchersRanges.tests.cpp:<line number>: PASSED:
REQUIRE_THAT( mocked1, RangeEquals( arr ) )
with expansion:
{ 1, 2, 3, 4 } elements are { 1, 2, 3, 4 }
MatchersRanges.tests.cpp:<line number>: PASSED:
REQUIRE( mocked1.m_derefed[0] )
with expansion:
true
MatchersRanges.tests.cpp:<line number>: PASSED:
REQUIRE( mocked1.m_derefed[1] )
with expansion:
true
MatchersRanges.tests.cpp:<line number>: PASSED:
REQUIRE( mocked1.m_derefed[2] )
with expansion:
true
MatchersRanges.tests.cpp:<line number>: PASSED:
REQUIRE( mocked1.m_derefed[3] )
with expansion:
true
-------------------------------------------------------------------------------
Usage of UnorderedRangeEquals range matcher
Basic usage
Empty container matches empty container
-------------------------------------------------------------------------------
MatchersRanges.tests.cpp:<line number>
...............................................................................
MatchersRanges.tests.cpp:<line number>: PASSED:
CHECK_THAT( empty_vector, UnorderedRangeEquals( empty_vector ) )
with expansion:
{ } unordered elements are { }
-------------------------------------------------------------------------------
Usage of UnorderedRangeEquals range matcher
Basic usage
Empty container does not match non-empty container
-------------------------------------------------------------------------------
MatchersRanges.tests.cpp:<line number>
...............................................................................
MatchersRanges.tests.cpp:<line number>: PASSED:
CHECK_THAT( empty_vector, !UnorderedRangeEquals( non_empty_vector ) )
with expansion:
{ } not unordered elements are { 1 }
MatchersRanges.tests.cpp:<line number>: PASSED:
CHECK_THAT( non_empty_vector, !UnorderedRangeEquals( empty_vector ) )
with expansion:
{ 1 } not unordered elements are { }
-------------------------------------------------------------------------------
Usage of UnorderedRangeEquals range matcher
Basic usage
Two equal 1-length non-empty containers
-------------------------------------------------------------------------------
MatchersRanges.tests.cpp:<line number>
...............................................................................
MatchersRanges.tests.cpp:<line number>: PASSED:
CHECK_THAT( non_empty_array, UnorderedRangeEquals( non_empty_array ) )
with expansion:
{ 1 } unordered elements are { 1 }
-------------------------------------------------------------------------------
Usage of UnorderedRangeEquals range matcher
Basic usage
Two equal-sized, equal, non-empty containers
-------------------------------------------------------------------------------
MatchersRanges.tests.cpp:<line number>
...............................................................................
MatchersRanges.tests.cpp:<line number>: PASSED:
CHECK_THAT( array_a, UnorderedRangeEquals( array_a ) )
with expansion:
{ 1, 2, 3 } unordered elements are { 1, 2, 3 }
-------------------------------------------------------------------------------
Usage of UnorderedRangeEquals range matcher
Basic usage
Two equal-sized, non-equal, non-empty containers
-------------------------------------------------------------------------------
MatchersRanges.tests.cpp:<line number>
...............................................................................
MatchersRanges.tests.cpp:<line number>: PASSED:
CHECK_THAT( array_a, !UnorderedRangeEquals( array_b ) )
with expansion:
{ 1, 2, 3 } not unordered elements are { 2, 2, 3 }
-------------------------------------------------------------------------------
Usage of UnorderedRangeEquals range matcher
Basic usage
Two non-equal-sized, non-empty containers
-------------------------------------------------------------------------------
MatchersRanges.tests.cpp:<line number>
...............................................................................
MatchersRanges.tests.cpp:<line number>: PASSED:
CHECK_THAT( vector_a, !UnorderedRangeEquals( vector_b ) )
with expansion:
{ 1, 2, 3 } not unordered elements are { 1, 2, 3, 4 }
-------------------------------------------------------------------------------
Usage of UnorderedRangeEquals range matcher
Custom predicate
Two equal non-empty containers (close enough)
-------------------------------------------------------------------------------
MatchersRanges.tests.cpp:<line number>
...............................................................................
MatchersRanges.tests.cpp:<line number>: PASSED:
CHECK_THAT( vector_a, UnorderedRangeEquals( vector_a_plus_1, close_enough ) )
with expansion:
{ 1, 10, 20 } unordered elements are { 11, 21, 2 }
-------------------------------------------------------------------------------
Usage of UnorderedRangeEquals range matcher
Custom predicate
Two non-equal non-empty containers (close enough)
-------------------------------------------------------------------------------
MatchersRanges.tests.cpp:<line number>
...............................................................................
MatchersRanges.tests.cpp:<line number>: PASSED:
CHECK_THAT( vector_a, !UnorderedRangeEquals( vector_b, close_enough ) )
with expansion:
{ 1, 10, 21 } not unordered elements are { 11, 21, 3 }
-------------------------------------------------------------------------------
Usage of UnorderedRangeEquals range matcher
Ranges that need ADL begin/end
-------------------------------------------------------------------------------
MatchersRanges.tests.cpp:<line number>
...............................................................................
MatchersRanges.tests.cpp:<line number>: PASSED:
REQUIRE_THAT( needs_adl1, UnorderedRangeEquals( needs_adl2 ) )
with expansion:
{ 1, 2, 3, 4, 5 } unordered elements are { 1, 2, 3, 4, 5 }
------------------------------------------------------------------------------- -------------------------------------------------------------------------------
Usage of the SizeIs range matcher Usage of the SizeIs range matcher
Some with stdlib containers Some with stdlib containers
@@ -14626,6 +15161,16 @@ with expansion:
<Element1 attr1="true" attr2="false"/> <Element1 attr1="true" attr2="false"/>
" ( contains: "attr1="true"" and contains: "attr2="false"" ) " ( contains: "attr1="true"" and contains: "attr2="false"" )
-------------------------------------------------------------------------------
a succeeding test can still be skipped
-------------------------------------------------------------------------------
Skip.tests.cpp:<line number>
...............................................................................
Skip.tests.cpp:<line number>: PASSED:
Skip.tests.cpp:<line number>: SKIPPED:
------------------------------------------------------------------------------- -------------------------------------------------------------------------------
analyse no analysis analyse no analysis
------------------------------------------------------------------------------- -------------------------------------------------------------------------------
@@ -15171,6 +15716,34 @@ FloatingPoint.tests.cpp:<line number>: PASSED:
with expansion: with expansion:
1 == 1 1 == 1
-------------------------------------------------------------------------------
dynamic skipping works with generators
-------------------------------------------------------------------------------
Skip.tests.cpp:<line number>
...............................................................................
Skip.tests.cpp:<line number>: SKIPPED:
explicitly with message:
skipping because answer = 41
-------------------------------------------------------------------------------
dynamic skipping works with generators
-------------------------------------------------------------------------------
Skip.tests.cpp:<line number>
...............................................................................
Skip.tests.cpp:<line number>: PASSED:
-------------------------------------------------------------------------------
dynamic skipping works with generators
-------------------------------------------------------------------------------
Skip.tests.cpp:<line number>
...............................................................................
Skip.tests.cpp:<line number>: SKIPPED:
explicitly with message:
skipping because answer = 43
------------------------------------------------------------------------------- -------------------------------------------------------------------------------
empty tags are not allowed empty tags are not allowed
------------------------------------------------------------------------------- -------------------------------------------------------------------------------
@@ -15246,6 +15819,67 @@ Misc.tests.cpp:<line number>
Misc.tests.cpp:<line number>: PASSED: Misc.tests.cpp:<line number>: PASSED:
-------------------------------------------------------------------------------
failed assertions before SKIP cause test case to fail
-------------------------------------------------------------------------------
Skip.tests.cpp:<line number>
...............................................................................
Skip.tests.cpp:<line number>: FAILED:
CHECK( 3 == 4 )
Skip.tests.cpp:<line number>: SKIPPED:
-------------------------------------------------------------------------------
failing for some generator values causes entire test case to fail
-------------------------------------------------------------------------------
Skip.tests.cpp:<line number>
...............................................................................
Skip.tests.cpp:<line number>: FAILED:
-------------------------------------------------------------------------------
failing for some generator values causes entire test case to fail
-------------------------------------------------------------------------------
Skip.tests.cpp:<line number>
...............................................................................
Skip.tests.cpp:<line number>: SKIPPED:
-------------------------------------------------------------------------------
failing for some generator values causes entire test case to fail
-------------------------------------------------------------------------------
Skip.tests.cpp:<line number>
...............................................................................
Skip.tests.cpp:<line number>: FAILED:
-------------------------------------------------------------------------------
failing for some generator values causes entire test case to fail
-------------------------------------------------------------------------------
Skip.tests.cpp:<line number>
...............................................................................
Skip.tests.cpp:<line number>: SKIPPED:
-------------------------------------------------------------------------------
failing in some unskipped sections causes entire test case to fail
skipped
-------------------------------------------------------------------------------
Skip.tests.cpp:<line number>
...............................................................................
Skip.tests.cpp:<line number>: SKIPPED:
-------------------------------------------------------------------------------
failing in some unskipped sections causes entire test case to fail
not skipped
-------------------------------------------------------------------------------
Skip.tests.cpp:<line number>
...............................................................................
Skip.tests.cpp:<line number>: FAILED:
------------------------------------------------------------------------------- -------------------------------------------------------------------------------
first tag first tag
------------------------------------------------------------------------------- -------------------------------------------------------------------------------
@@ -15741,6 +16375,37 @@ Misc.tests.cpp:<line number>: PASSED:
with expansion: with expansion:
1 != 2 1 != 2
-------------------------------------------------------------------------------
nested sections can be skipped dynamically at runtime
A
-------------------------------------------------------------------------------
Skip.tests.cpp:<line number>
...............................................................................
No assertions in section 'A'
-------------------------------------------------------------------------------
nested sections can be skipped dynamically at runtime
B
B1
-------------------------------------------------------------------------------
Skip.tests.cpp:<line number>
...............................................................................
No assertions in section 'B1'
-------------------------------------------------------------------------------
nested sections can be skipped dynamically at runtime
B
B2
-------------------------------------------------------------------------------
Skip.tests.cpp:<line number>
...............................................................................
Skip.tests.cpp:<line number>: SKIPPED:
------------------------------------------------------------------------------- -------------------------------------------------------------------------------
non streamable - with conv. op non streamable - with conv. op
------------------------------------------------------------------------------- -------------------------------------------------------------------------------
@@ -16342,6 +17007,33 @@ Misc.tests.cpp:<line number>
No assertions in test case 'second tag' No assertions in test case 'second tag'
-------------------------------------------------------------------------------
sections can be skipped dynamically at runtime
not skipped
-------------------------------------------------------------------------------
Skip.tests.cpp:<line number>
...............................................................................
Skip.tests.cpp:<line number>: PASSED:
-------------------------------------------------------------------------------
sections can be skipped dynamically at runtime
skipped
-------------------------------------------------------------------------------
Skip.tests.cpp:<line number>
...............................................................................
Skip.tests.cpp:<line number>: SKIPPED:
-------------------------------------------------------------------------------
sections can be skipped dynamically at runtime
also not skipped
-------------------------------------------------------------------------------
Skip.tests.cpp:<line number>
...............................................................................
Skip.tests.cpp:<line number>: PASSED:
------------------------------------------------------------------------------- -------------------------------------------------------------------------------
send a single char to INFO send a single char to INFO
------------------------------------------------------------------------------- -------------------------------------------------------------------------------
@@ -16376,6 +17068,16 @@ Tag.tests.cpp:<line number>: PASSED:
with expansion: with expansion:
{ {?}, {?} } ( Contains: {?} and Contains: {?} ) { {?}, {?} } ( Contains: {?} and Contains: {?} )
-------------------------------------------------------------------------------
skipped tests can optionally provide a reason
-------------------------------------------------------------------------------
Skip.tests.cpp:<line number>
...............................................................................
Skip.tests.cpp:<line number>: SKIPPED:
explicitly with message:
skipping because answer = 43
------------------------------------------------------------------------------- -------------------------------------------------------------------------------
splitString splitString
------------------------------------------------------------------------------- -------------------------------------------------------------------------------
@@ -16803,6 +17505,14 @@ Tag.tests.cpp:<line number>: PASSED:
with expansion: with expansion:
magic.tag == magic.tag magic.tag == magic.tag
-------------------------------------------------------------------------------
tests can be skipped dynamically at runtime
-------------------------------------------------------------------------------
Skip.tests.cpp:<line number>
...............................................................................
Skip.tests.cpp:<line number>: SKIPPED:
------------------------------------------------------------------------------- -------------------------------------------------------------------------------
thrown std::strings are translated thrown std::strings are translated
------------------------------------------------------------------------------- -------------------------------------------------------------------------------
@@ -17510,6 +18220,6 @@ Misc.tests.cpp:<line number>
Misc.tests.cpp:<line number>: PASSED: Misc.tests.cpp:<line number>: PASSED:
=============================================================================== ===============================================================================
test cases: 394 | 304 passed | 83 failed | 7 failed as expected test cases: 409 | 309 passed | 84 failed | 5 skipped | 11 failed as expected
assertions: 2159 | 1989 passed | 143 failed | 27 failed as expected assertions: 2226 | 2049 passed | 145 failed | 32 failed as expected

View File

@@ -761,6 +761,16 @@ with expansion:
0.0f not is within 1 ULPs of -1.40129846e-45f ([-2.80259693e-45, -0. 0.0f not is within 1 ULPs of -1.40129846e-45f ([-2.80259693e-45, -0.
00000000e+00]) 00000000e+00])
-------------------------------------------------------------------------------
#2615 - Throwing in constructor generator fails test case but does not abort
-------------------------------------------------------------------------------
Generators.tests.cpp:<line number>
...............................................................................
Generators.tests.cpp:<line number>: FAILED:
due to unexpected exception with message:
failure to init
------------------------------------------------------------------------------- -------------------------------------------------------------------------------
#748 - captures with unexpected exceptions #748 - captures with unexpected exceptions
outside assertions outside assertions
@@ -941,6 +951,6 @@ Condition.tests.cpp:<line number>: FAILED:
CHECK( true != true ) CHECK( true != true )
=============================================================================== ===============================================================================
test cases: 32 | 27 passed | 3 failed | 2 failed as expected test cases: 33 | 27 passed | 3 failed | 3 failed as expected
assertions: 101 | 94 passed | 4 failed | 3 failed as expected assertions: 102 | 94 passed | 4 failed | 4 failed as expected

View File

@@ -6,3 +6,6 @@ A string sent to stderr via clog
Message from section one Message from section one
Message from section two Message from section two
loose text artifact loose text artifact
a!
b1!
!

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@@ -164,6 +164,8 @@ ok {test-number} - smallest_non_zero, !WithinULP( -smallest_non_zero, 1 ) for: 0
ok {test-number} - smallest_non_zero, WithinULP( -smallest_non_zero, 2 ) for: 0.0f is within 2 ULPs of -1.40129846e-45f ([-4.20389539e-45, 1.40129846e-45]) ok {test-number} - smallest_non_zero, WithinULP( -smallest_non_zero, 2 ) for: 0.0f is within 2 ULPs of -1.40129846e-45f ([-4.20389539e-45, 1.40129846e-45])
# #2152 - ULP checks between differently signed values were wrong - float # #2152 - ULP checks between differently signed values were wrong - float
ok {test-number} - smallest_non_zero, !WithinULP( -smallest_non_zero, 1 ) for: 0.0f not is within 1 ULPs of -1.40129846e-45f ([-2.80259693e-45, -0.00000000e+00]) ok {test-number} - smallest_non_zero, !WithinULP( -smallest_non_zero, 1 ) for: 0.0f not is within 1 ULPs of -1.40129846e-45f ([-2.80259693e-45, -0.00000000e+00])
# #2615 - Throwing in constructor generator fails test case but does not abort
not ok {test-number} - unexpected exception with message: 'failure to init'
# #748 - captures with unexpected exceptions # #748 - captures with unexpected exceptions
not ok {test-number} - unexpected exception with message: 'answer := 42' with 1 message: 'expected exception' not ok {test-number} - unexpected exception with message: 'answer := 42' with 1 message: 'expected exception'
# #748 - captures with unexpected exceptions # #748 - captures with unexpected exceptions
@@ -1076,6 +1078,14 @@ not ok {test-number} - throwsSpecialException( 4 ), SpecialException, ExceptionM
ok {test-number} - throwsSpecialException( 1 ), SpecialException, ExceptionMatcher{ 1 } for: SpecialException::what special exception has value of 1 ok {test-number} - throwsSpecialException( 1 ), SpecialException, ExceptionMatcher{ 1 } for: SpecialException::what special exception has value of 1
# Exception matchers that succeed # Exception matchers that succeed
ok {test-number} - throwsSpecialException( 2 ), SpecialException, ExceptionMatcher{ 2 } for: SpecialException::what special exception has value of 2 ok {test-number} - throwsSpecialException( 2 ), SpecialException, ExceptionMatcher{ 2 } for: SpecialException::what special exception has value of 2
# Exception message can be matched
ok {test-number} - throwsDerivedException(), DerivedException, MessageMatches( StartsWith( "Derived" ) ) for: DerivedException::what matches "starts with: "Derived""
# Exception message can be matched
ok {test-number} - throwsDerivedException(), DerivedException, MessageMatches( EndsWith( "::what" ) ) for: DerivedException::what matches "ends with: "::what""
# Exception message can be matched
ok {test-number} - throwsDerivedException(), DerivedException, MessageMatches( !StartsWith( "::what" ) ) for: DerivedException::what matches "not starts with: "::what""
# Exception message can be matched
ok {test-number} - throwsSpecialException( 2 ), SpecialException, MessageMatches( StartsWith( "Special" ) ) for: SpecialException::what matches "starts with: "Special""
# Exception messages can be tested for # Exception messages can be tested for
ok {test-number} - thisThrows(), "expected exception" for: "expected exception" equals: "expected exception" ok {test-number} - thisThrows(), "expected exception" for: "expected exception" equals: "expected exception"
# Exception messages can be tested for # Exception messages can be tested for
@@ -1120,6 +1130,8 @@ ok {test-number} - Factorial(2) == 2 for: 2 == 2
ok {test-number} - Factorial(3) == 6 for: 6 == 6 ok {test-number} - Factorial(3) == 6 for: 6 == 6
# Factorials are computed # Factorials are computed
ok {test-number} - Factorial(10) == 3628800 for: 3628800 (0x<hex digits>) == 3628800 (0x<hex digits>) ok {test-number} - Factorial(10) == 3628800 for: 3628800 (0x<hex digits>) == 3628800 (0x<hex digits>)
# Filter generator throws exception for empty generator
ok {test-number} - filter( []( int ) { return false; }, value( 3 ) ), Catch::GeneratorException
# Floating point matchers: double # Floating point matchers: double
ok {test-number} - 10., WithinRel( 11.1, 0.1 ) for: 10.0 and 11.1 are within 10% of each other ok {test-number} - 10., WithinRel( 11.1, 0.1 ) for: 10.0 and 11.1 are within 10% of each other
# Floating point matchers: double # Floating point matchers: double
@@ -1178,6 +1190,8 @@ ok {test-number} - WithinRel( 1., 0. )
ok {test-number} - WithinRel( 1., -0.2 ), std::domain_error ok {test-number} - WithinRel( 1., -0.2 ), std::domain_error
# Floating point matchers: double # Floating point matchers: double
ok {test-number} - WithinRel( 1., 1. ), std::domain_error ok {test-number} - WithinRel( 1., 1. ), std::domain_error
# Floating point matchers: double
ok {test-number} - 1., !IsNaN() for: 1.0 not is NaN
# Floating point matchers: float # Floating point matchers: float
ok {test-number} - 10.f, WithinRel( 11.1f, 0.1f ) for: 10.0f and 11.1 are within 10% of each other ok {test-number} - 10.f, WithinRel( 11.1f, 0.1f ) for: 10.0f and 11.1 are within 10% of each other
# Floating point matchers: float # Floating point matchers: float
@@ -1242,6 +1256,8 @@ ok {test-number} - WithinRel( 1.f, 0.f )
ok {test-number} - WithinRel( 1.f, -0.2f ), std::domain_error ok {test-number} - WithinRel( 1.f, -0.2f ), std::domain_error
# Floating point matchers: float # Floating point matchers: float
ok {test-number} - WithinRel( 1.f, 1.f ), std::domain_error ok {test-number} - WithinRel( 1.f, 1.f ), std::domain_error
# Floating point matchers: float
ok {test-number} - 1., !IsNaN() for: 1.0 not is NaN
# Generators -- adapters # Generators -- adapters
ok {test-number} - i % 2 == 0 for: 0 == 0 ok {test-number} - i % 2 == 0 for: 0 == 0
# Generators -- adapters # Generators -- adapters
@@ -3215,6 +3231,40 @@ ok {test-number} - trim(StringRef(leading_whitespace)) == StringRef(no_whitespac
ok {test-number} - trim(StringRef(trailing_whitespace)) == StringRef(no_whitespace) for: There is no extra whitespace here == There is no extra whitespace here ok {test-number} - trim(StringRef(trailing_whitespace)) == StringRef(no_whitespace) for: There is no extra whitespace here == There is no extra whitespace here
# Trim strings # Trim strings
ok {test-number} - trim(StringRef(whitespace_at_both_ends)) == StringRef(no_whitespace) for: There is no extra whitespace here == There is no extra whitespace here ok {test-number} - trim(StringRef(whitespace_at_both_ends)) == StringRef(no_whitespace) for: There is no extra whitespace here == There is no extra whitespace here
# Type conversions of RangeEquals and similar
ok {test-number} - array_int_a, RangeEquals( c_array ) for: { 1, 2, 3 } elements are { 1, 2, 3 }
# Type conversions of RangeEquals and similar
ok {test-number} - array_int_a, UnorderedRangeEquals( c_array ) for: { 1, 2, 3 } unordered elements are { 1, 2, 3 }
# Type conversions of RangeEquals and similar
ok {test-number} - array_int_3, !RangeEquals( array_int_4 ) for: { 1, 2, 3 } not elements are { 1, 2, 3, 4 }
# Type conversions of RangeEquals and similar
ok {test-number} - array_int_3, !UnorderedRangeEquals( array_int_4 ) for: { 1, 2, 3 } not unordered elements are { 1, 2, 3, 4 }
# Type conversions of RangeEquals and similar
ok {test-number} - array_int_a, RangeEquals( vector_char_a ) for: { 1, 2, 3 } elements are { 1, 2, 3 }
# Type conversions of RangeEquals and similar
ok {test-number} - array_int_a, UnorderedRangeEquals( vector_char_a ) for: { 1, 2, 3 } unordered elements are { 1, 2, 3 }
# Type conversions of RangeEquals and similar
ok {test-number} - with 1 message: 'ContainerIsRandomAccess( array_int_a ) != ContainerIsRandomAccess( list_char_a )'
# Type conversions of RangeEquals and similar
ok {test-number} - array_int_a, RangeEquals( list_char_a ) for: { 1, 2, 3 } elements are { 1, 2, 3 }
# Type conversions of RangeEquals and similar
ok {test-number} - array_int_a, UnorderedRangeEquals( list_char_a ) for: { 1, 2, 3 } unordered elements are { 1, 2, 3 }
# Type conversions of RangeEquals and similar
ok {test-number} - vector_int_a, RangeEquals( vector_char_a ) for: { 1, 2, 3 } elements are { 1, 2, 3 }
# Type conversions of RangeEquals and similar
ok {test-number} - vector_int_a, UnorderedRangeEquals( vector_char_a ) for: { 1, 2, 3 } unordered elements are { 1, 2, 3 }
# Type conversions of RangeEquals and similar
ok {test-number} - vector_int_a, !RangeEquals( vector_char_b ) for: { 1, 2, 3 } not elements are { 1, 2, 2 }
# Type conversions of RangeEquals and similar
ok {test-number} - vector_int_a, !UnorderedRangeEquals( vector_char_b ) for: { 1, 2, 3 } not unordered elements are { 1, 2, 2 }
# Type conversions of RangeEquals and similar
ok {test-number} - a, !RangeEquals( b ) for: { 1, 2, 3 } not elements are { 3, 2, 1 }
# Type conversions of RangeEquals and similar
ok {test-number} - a, UnorderedRangeEquals( b ) for: { 1, 2, 3 } unordered elements are { 3, 2, 1 }
# Type conversions of RangeEquals and similar
ok {test-number} - vector_a, RangeEquals( array_a_plus_1, close_enough ) for: { 1, 2, 3 } elements are { 2, 3, 4 }
# Type conversions of RangeEquals and similar
ok {test-number} - vector_a, UnorderedRangeEquals( array_a_plus_1, close_enough ) for: { 1, 2, 3 } unordered elements are { 2, 3, 4 }
# Unexpected exceptions can be translated # Unexpected exceptions can be translated
not ok {test-number} - unexpected exception with message: '3.14' not ok {test-number} - unexpected exception with message: '3.14'
# Upcasting special member functions # Upcasting special member functions
@@ -3425,6 +3475,70 @@ ok {test-number} - mocked.m_derefed[2] for: true
ok {test-number} - !(mocked.m_derefed[3]) for: !false ok {test-number} - !(mocked.m_derefed[3]) for: !false
# Usage of NoneTrue range matcher # Usage of NoneTrue range matcher
ok {test-number} - !(mocked.m_derefed[4]) for: !false ok {test-number} - !(mocked.m_derefed[4]) for: !false
# Usage of RangeEquals range matcher
ok {test-number} - empty_vector, RangeEquals( empty_vector ) for: { } elements are { }
# Usage of RangeEquals range matcher
ok {test-number} - empty_vector, !RangeEquals( non_empty_vector ) for: { } not elements are { 1 }
# Usage of RangeEquals range matcher
ok {test-number} - non_empty_vector, !RangeEquals( empty_vector ) for: { 1 } not elements are { }
# Usage of RangeEquals range matcher
ok {test-number} - non_empty_array, RangeEquals( non_empty_array ) for: { 1 } elements are { 1 }
# Usage of RangeEquals range matcher
ok {test-number} - array_a, RangeEquals( array_a ) for: { 1, 2, 3 } elements are { 1, 2, 3 }
# Usage of RangeEquals range matcher
ok {test-number} - array_a, !RangeEquals( array_b ) for: { 1, 2, 3 } not elements are { 2, 2, 3 }
# Usage of RangeEquals range matcher
ok {test-number} - array_a, !RangeEquals( array_c ) for: { 1, 2, 3 } not elements are { 1, 2, 2 }
# Usage of RangeEquals range matcher
ok {test-number} - vector_a, !RangeEquals( vector_b ) for: { 1, 2, 3 } not elements are { 1, 2, 3, 4 }
# Usage of RangeEquals range matcher
ok {test-number} - vector_a, RangeEquals( vector_a_plus_1, close_enough ) for: { 1, 2, 3 } elements are { 2, 3, 4 }
# Usage of RangeEquals range matcher
ok {test-number} - vector_a, !RangeEquals( vector_b, close_enough ) for: { 1, 2, 3 } not elements are { 3, 3, 4 }
# Usage of RangeEquals range matcher
ok {test-number} - needs_adl1, RangeEquals( needs_adl2 ) for: { 1, 2, 3, 4, 5 } elements are { 1, 2, 3, 4, 5 }
# Usage of RangeEquals range matcher
ok {test-number} - needs_adl1, RangeEquals( needs_adl3, []( int l, int r ) { return l + 1 == r; } ) for: { 1, 2, 3, 4, 5 } elements are { 2, 3, 4, 5, 6 }
# Usage of RangeEquals range matcher
ok {test-number} - mocked1, !RangeEquals( arr ) for: { 1, 2, 3, 4 } not elements are { 1, 2, 4, 4 }
# Usage of RangeEquals range matcher
ok {test-number} - mocked1.m_derefed[0] for: true
# Usage of RangeEquals range matcher
ok {test-number} - mocked1.m_derefed[1] for: true
# Usage of RangeEquals range matcher
ok {test-number} - mocked1.m_derefed[2] for: true
# Usage of RangeEquals range matcher
ok {test-number} - !(mocked1.m_derefed[3]) for: !false
# Usage of RangeEquals range matcher
ok {test-number} - mocked1, RangeEquals( arr ) for: { 1, 2, 3, 4 } elements are { 1, 2, 3, 4 }
# Usage of RangeEquals range matcher
ok {test-number} - mocked1.m_derefed[0] for: true
# Usage of RangeEquals range matcher
ok {test-number} - mocked1.m_derefed[1] for: true
# Usage of RangeEquals range matcher
ok {test-number} - mocked1.m_derefed[2] for: true
# Usage of RangeEquals range matcher
ok {test-number} - mocked1.m_derefed[3] for: true
# Usage of UnorderedRangeEquals range matcher
ok {test-number} - empty_vector, UnorderedRangeEquals( empty_vector ) for: { } unordered elements are { }
# Usage of UnorderedRangeEquals range matcher
ok {test-number} - empty_vector, !UnorderedRangeEquals( non_empty_vector ) for: { } not unordered elements are { 1 }
# Usage of UnorderedRangeEquals range matcher
ok {test-number} - non_empty_vector, !UnorderedRangeEquals( empty_vector ) for: { 1 } not unordered elements are { }
# Usage of UnorderedRangeEquals range matcher
ok {test-number} - non_empty_array, UnorderedRangeEquals( non_empty_array ) for: { 1 } unordered elements are { 1 }
# Usage of UnorderedRangeEquals range matcher
ok {test-number} - array_a, UnorderedRangeEquals( array_a ) for: { 1, 2, 3 } unordered elements are { 1, 2, 3 }
# Usage of UnorderedRangeEquals range matcher
ok {test-number} - array_a, !UnorderedRangeEquals( array_b ) for: { 1, 2, 3 } not unordered elements are { 2, 2, 3 }
# Usage of UnorderedRangeEquals range matcher
ok {test-number} - vector_a, !UnorderedRangeEquals( vector_b ) for: { 1, 2, 3 } not unordered elements are { 1, 2, 3, 4 }
# Usage of UnorderedRangeEquals range matcher
ok {test-number} - vector_a, UnorderedRangeEquals( vector_a_plus_1, close_enough ) for: { 1, 10, 20 } unordered elements are { 11, 21, 2 }
# Usage of UnorderedRangeEquals range matcher
ok {test-number} - vector_a, !UnorderedRangeEquals( vector_b, close_enough ) for: { 1, 10, 21 } not unordered elements are { 11, 21, 3 }
# Usage of UnorderedRangeEquals range matcher
ok {test-number} - needs_adl1, UnorderedRangeEquals( needs_adl2 ) for: { 1, 2, 3, 4, 5 } unordered elements are { 1, 2, 3, 4, 5 }
# Usage of the SizeIs range matcher # Usage of the SizeIs range matcher
ok {test-number} - empty_vec, SizeIs(0) for: { } has size == 0 ok {test-number} - empty_vec, SizeIs(0) for: { } has size == 0
# Usage of the SizeIs range matcher # Usage of the SizeIs range matcher
@@ -3601,6 +3715,10 @@ ok {test-number} - encode( "[\x01]" ) == "[\\x01]" for: "[\x01]" == "[\x01]"
ok {test-number} - encode( "[\x7F]" ) == "[\\x7F]" for: "[\x7F]" == "[\x7F]" ok {test-number} - encode( "[\x7F]" ) == "[\\x7F]" for: "[\x7F]" == "[\x7F]"
# XmlWriter writes boolean attributes as true/false # XmlWriter writes boolean attributes as true/false
ok {test-number} - stream.str(), ContainsSubstring(R"(attr1="true")") && ContainsSubstring(R"(attr2="false")") for: "<?xml version="1.0" encoding="UTF-8"?> <Element1 attr1="true" attr2="false"/> " ( contains: "attr1="true"" and contains: "attr2="false"" ) ok {test-number} - stream.str(), ContainsSubstring(R"(attr1="true")") && ContainsSubstring(R"(attr2="false")") for: "<?xml version="1.0" encoding="UTF-8"?> <Element1 attr1="true" attr2="false"/> " ( contains: "attr1="true"" and contains: "attr2="false"" )
# a succeeding test can still be skipped
ok {test-number} -
# a succeeding test can still be skipped
ok {test-number} - # SKIP
# analyse no analysis # analyse no analysis
ok {test-number} - analysis.mean.point.count() == 23 for: 23.0 == 23 ok {test-number} - analysis.mean.point.count() == 23 for: 23.0 == 23
# analyse no analysis # analyse no analysis
@@ -3771,6 +3889,12 @@ ok {test-number} - convertToBits( -0. ) == ( 1ULL << 63 ) for: 92233720368547758
ok {test-number} - convertToBits( std::numeric_limits<float>::denorm_min() ) == 1 for: 1 == 1 ok {test-number} - convertToBits( std::numeric_limits<float>::denorm_min() ) == 1 for: 1 == 1
# convertToBits # convertToBits
ok {test-number} - convertToBits( std::numeric_limits<double>::denorm_min() ) == 1 for: 1 == 1 ok {test-number} - convertToBits( std::numeric_limits<double>::denorm_min() ) == 1 for: 1 == 1
# dynamic skipping works with generators
ok {test-number} - # SKIP 'skipping because answer = 41'
# dynamic skipping works with generators
ok {test-number} -
# dynamic skipping works with generators
ok {test-number} - # SKIP 'skipping because answer = 43'
# empty tags are not allowed # empty tags are not allowed
ok {test-number} - Catch::TestCaseInfo("", { "test with an empty tag", "[]" }, dummySourceLineInfo) ok {test-number} - Catch::TestCaseInfo("", { "test with an empty tag", "[]" }, dummySourceLineInfo)
# erfc_inv # erfc_inv
@@ -3789,6 +3913,22 @@ ok {test-number} -
ok {test-number} - ok {test-number} -
# even more nested SECTION tests # even more nested SECTION tests
ok {test-number} - ok {test-number} -
# failed assertions before SKIP cause test case to fail
not ok {test-number} - 3 == 4
# failed assertions before SKIP cause test case to fail
ok {test-number} - # SKIP
# failing for some generator values causes entire test case to fail
not ok {test-number} - explicitly
# failing for some generator values causes entire test case to fail
ok {test-number} - # SKIP
# failing for some generator values causes entire test case to fail
not ok {test-number} - explicitly
# failing for some generator values causes entire test case to fail
ok {test-number} - # SKIP
# failing in some unskipped sections causes entire test case to fail
ok {test-number} - # SKIP
# failing in some unskipped sections causes entire test case to fail
not ok {test-number} - explicitly
loose text artifact loose text artifact
# is_unary_function # is_unary_function
ok {test-number} - with 1 message: 'Catch::Clara::Detail::is_unary_function<decltype(unary1)>::value' ok {test-number} - with 1 message: 'Catch::Clara::Detail::is_unary_function<decltype(unary1)>::value'
@@ -3898,6 +4038,11 @@ ok {test-number} - a != b for: 1 != 2
ok {test-number} - b != a for: 2 != 1 ok {test-number} - b != a for: 2 != 1
# nested SECTION tests # nested SECTION tests
ok {test-number} - a != b for: 1 != 2 ok {test-number} - a != b for: 1 != 2
a!
b1!
# nested sections can be skipped dynamically at runtime
ok {test-number} - # SKIP
!
# non streamable - with conv. op # non streamable - with conv. op
ok {test-number} - s == "7" for: "7" == "7" ok {test-number} - s == "7" for: "7" == "7"
# non-copyable objects # non-copyable objects
@@ -4062,12 +4207,20 @@ ok {test-number} - Timing.elapsed >= time for: 128 ns >= 100 ns
ok {test-number} - Timing.result == Timing.iterations + 17 for: 145 == 145 ok {test-number} - Timing.result == Timing.iterations + 17 for: 145 == 145
# run_for_at_least, int # run_for_at_least, int
ok {test-number} - Timing.iterations >= time.count() for: 128 >= 100 ok {test-number} - Timing.iterations >= time.count() for: 128 >= 100
# sections can be skipped dynamically at runtime
ok {test-number} -
# sections can be skipped dynamically at runtime
ok {test-number} - # SKIP
# sections can be skipped dynamically at runtime
ok {test-number} -
# send a single char to INFO # send a single char to INFO
not ok {test-number} - false with 1 message: '3' not ok {test-number} - false with 1 message: '3'
# sends information to INFO # sends information to INFO
not ok {test-number} - false with 2 messages: 'hi' and 'i := 7' not ok {test-number} - false with 2 messages: 'hi' and 'i := 7'
# shortened hide tags are split apart # shortened hide tags are split apart
ok {test-number} - testcase.tags, VectorContains( Tag( "magic-tag" ) ) && VectorContains( Tag( "."_catch_sr ) ) for: { {?}, {?} } ( Contains: {?} and Contains: {?} ) ok {test-number} - testcase.tags, VectorContains( Tag( "magic-tag" ) ) && VectorContains( Tag( "."_catch_sr ) ) for: { {?}, {?} } ( Contains: {?} and Contains: {?} )
# skipped tests can optionally provide a reason
ok {test-number} - # SKIP 'skipping because answer = 43'
# splitString # splitString
ok {test-number} - splitStringRef("", ','), Equals(std::vector<StringRef>()) for: { } Equals: { } ok {test-number} - splitStringRef("", ','), Equals(std::vector<StringRef>()) for: { } Equals: { }
# splitString # splitString
@@ -4150,6 +4303,8 @@ ok {test-number} - strlen(std::get<0>(data)) == static_cast<size_t>(std::get<1>(
ok {test-number} - testcase.tags.size() == 1 for: 1 == 1 ok {test-number} - testcase.tags.size() == 1 for: 1 == 1
# tags with dots in later positions are not parsed as hidden # tags with dots in later positions are not parsed as hidden
ok {test-number} - testcase.tags[0].original == "magic.tag"_catch_sr for: magic.tag == magic.tag ok {test-number} - testcase.tags[0].original == "magic.tag"_catch_sr for: magic.tag == magic.tag
# tests can be skipped dynamically at runtime
ok {test-number} - # SKIP
# thrown std::strings are translated # thrown std::strings are translated
not ok {test-number} - unexpected exception with message: 'Why would you throw a std::string?' not ok {test-number} - unexpected exception with message: 'Why would you throw a std::string?'
# toString on const wchar_t const pointer returns the string contents # toString on const wchar_t const pointer returns the string contents
@@ -4322,5 +4477,5 @@ ok {test-number} - q3 == 23. for: 23.0 == 23.0
ok {test-number} - ok {test-number} -
# xmlentitycheck # xmlentitycheck
ok {test-number} - ok {test-number} -
1..2159 1..2237

View File

@@ -162,6 +162,8 @@ ok {test-number} - smallest_non_zero, !WithinULP( -smallest_non_zero, 1 ) for: 0
ok {test-number} - smallest_non_zero, WithinULP( -smallest_non_zero, 2 ) for: 0.0f is within 2 ULPs of -1.40129846e-45f ([-4.20389539e-45, 1.40129846e-45]) ok {test-number} - smallest_non_zero, WithinULP( -smallest_non_zero, 2 ) for: 0.0f is within 2 ULPs of -1.40129846e-45f ([-4.20389539e-45, 1.40129846e-45])
# #2152 - ULP checks between differently signed values were wrong - float # #2152 - ULP checks between differently signed values were wrong - float
ok {test-number} - smallest_non_zero, !WithinULP( -smallest_non_zero, 1 ) for: 0.0f not is within 1 ULPs of -1.40129846e-45f ([-2.80259693e-45, -0.00000000e+00]) ok {test-number} - smallest_non_zero, !WithinULP( -smallest_non_zero, 1 ) for: 0.0f not is within 1 ULPs of -1.40129846e-45f ([-2.80259693e-45, -0.00000000e+00])
# #2615 - Throwing in constructor generator fails test case but does not abort
not ok {test-number} - unexpected exception with message: 'failure to init'
# #748 - captures with unexpected exceptions # #748 - captures with unexpected exceptions
not ok {test-number} - unexpected exception with message: 'answer := 42' with 1 message: 'expected exception' not ok {test-number} - unexpected exception with message: 'answer := 42' with 1 message: 'expected exception'
# #748 - captures with unexpected exceptions # #748 - captures with unexpected exceptions
@@ -1074,6 +1076,14 @@ not ok {test-number} - throwsSpecialException( 4 ), SpecialException, ExceptionM
ok {test-number} - throwsSpecialException( 1 ), SpecialException, ExceptionMatcher{ 1 } for: SpecialException::what special exception has value of 1 ok {test-number} - throwsSpecialException( 1 ), SpecialException, ExceptionMatcher{ 1 } for: SpecialException::what special exception has value of 1
# Exception matchers that succeed # Exception matchers that succeed
ok {test-number} - throwsSpecialException( 2 ), SpecialException, ExceptionMatcher{ 2 } for: SpecialException::what special exception has value of 2 ok {test-number} - throwsSpecialException( 2 ), SpecialException, ExceptionMatcher{ 2 } for: SpecialException::what special exception has value of 2
# Exception message can be matched
ok {test-number} - throwsDerivedException(), DerivedException, MessageMatches( StartsWith( "Derived" ) ) for: DerivedException::what matches "starts with: "Derived""
# Exception message can be matched
ok {test-number} - throwsDerivedException(), DerivedException, MessageMatches( EndsWith( "::what" ) ) for: DerivedException::what matches "ends with: "::what""
# Exception message can be matched
ok {test-number} - throwsDerivedException(), DerivedException, MessageMatches( !StartsWith( "::what" ) ) for: DerivedException::what matches "not starts with: "::what""
# Exception message can be matched
ok {test-number} - throwsSpecialException( 2 ), SpecialException, MessageMatches( StartsWith( "Special" ) ) for: SpecialException::what matches "starts with: "Special""
# Exception messages can be tested for # Exception messages can be tested for
ok {test-number} - thisThrows(), "expected exception" for: "expected exception" equals: "expected exception" ok {test-number} - thisThrows(), "expected exception" for: "expected exception" equals: "expected exception"
# Exception messages can be tested for # Exception messages can be tested for
@@ -1118,6 +1128,8 @@ ok {test-number} - Factorial(2) == 2 for: 2 == 2
ok {test-number} - Factorial(3) == 6 for: 6 == 6 ok {test-number} - Factorial(3) == 6 for: 6 == 6
# Factorials are computed # Factorials are computed
ok {test-number} - Factorial(10) == 3628800 for: 3628800 (0x<hex digits>) == 3628800 (0x<hex digits>) ok {test-number} - Factorial(10) == 3628800 for: 3628800 (0x<hex digits>) == 3628800 (0x<hex digits>)
# Filter generator throws exception for empty generator
ok {test-number} - filter( []( int ) { return false; }, value( 3 ) ), Catch::GeneratorException
# Floating point matchers: double # Floating point matchers: double
ok {test-number} - 10., WithinRel( 11.1, 0.1 ) for: 10.0 and 11.1 are within 10% of each other ok {test-number} - 10., WithinRel( 11.1, 0.1 ) for: 10.0 and 11.1 are within 10% of each other
# Floating point matchers: double # Floating point matchers: double
@@ -1176,6 +1188,8 @@ ok {test-number} - WithinRel( 1., 0. )
ok {test-number} - WithinRel( 1., -0.2 ), std::domain_error ok {test-number} - WithinRel( 1., -0.2 ), std::domain_error
# Floating point matchers: double # Floating point matchers: double
ok {test-number} - WithinRel( 1., 1. ), std::domain_error ok {test-number} - WithinRel( 1., 1. ), std::domain_error
# Floating point matchers: double
ok {test-number} - 1., !IsNaN() for: 1.0 not is NaN
# Floating point matchers: float # Floating point matchers: float
ok {test-number} - 10.f, WithinRel( 11.1f, 0.1f ) for: 10.0f and 11.1 are within 10% of each other ok {test-number} - 10.f, WithinRel( 11.1f, 0.1f ) for: 10.0f and 11.1 are within 10% of each other
# Floating point matchers: float # Floating point matchers: float
@@ -1240,6 +1254,8 @@ ok {test-number} - WithinRel( 1.f, 0.f )
ok {test-number} - WithinRel( 1.f, -0.2f ), std::domain_error ok {test-number} - WithinRel( 1.f, -0.2f ), std::domain_error
# Floating point matchers: float # Floating point matchers: float
ok {test-number} - WithinRel( 1.f, 1.f ), std::domain_error ok {test-number} - WithinRel( 1.f, 1.f ), std::domain_error
# Floating point matchers: float
ok {test-number} - 1., !IsNaN() for: 1.0 not is NaN
# Generators -- adapters # Generators -- adapters
ok {test-number} - i % 2 == 0 for: 0 == 0 ok {test-number} - i % 2 == 0 for: 0 == 0
# Generators -- adapters # Generators -- adapters
@@ -3208,6 +3224,40 @@ ok {test-number} - trim(StringRef(leading_whitespace)) == StringRef(no_whitespac
ok {test-number} - trim(StringRef(trailing_whitespace)) == StringRef(no_whitespace) for: There is no extra whitespace here == There is no extra whitespace here ok {test-number} - trim(StringRef(trailing_whitespace)) == StringRef(no_whitespace) for: There is no extra whitespace here == There is no extra whitespace here
# Trim strings # Trim strings
ok {test-number} - trim(StringRef(whitespace_at_both_ends)) == StringRef(no_whitespace) for: There is no extra whitespace here == There is no extra whitespace here ok {test-number} - trim(StringRef(whitespace_at_both_ends)) == StringRef(no_whitespace) for: There is no extra whitespace here == There is no extra whitespace here
# Type conversions of RangeEquals and similar
ok {test-number} - array_int_a, RangeEquals( c_array ) for: { 1, 2, 3 } elements are { 1, 2, 3 }
# Type conversions of RangeEquals and similar
ok {test-number} - array_int_a, UnorderedRangeEquals( c_array ) for: { 1, 2, 3 } unordered elements are { 1, 2, 3 }
# Type conversions of RangeEquals and similar
ok {test-number} - array_int_3, !RangeEquals( array_int_4 ) for: { 1, 2, 3 } not elements are { 1, 2, 3, 4 }
# Type conversions of RangeEquals and similar
ok {test-number} - array_int_3, !UnorderedRangeEquals( array_int_4 ) for: { 1, 2, 3 } not unordered elements are { 1, 2, 3, 4 }
# Type conversions of RangeEquals and similar
ok {test-number} - array_int_a, RangeEquals( vector_char_a ) for: { 1, 2, 3 } elements are { 1, 2, 3 }
# Type conversions of RangeEquals and similar
ok {test-number} - array_int_a, UnorderedRangeEquals( vector_char_a ) for: { 1, 2, 3 } unordered elements are { 1, 2, 3 }
# Type conversions of RangeEquals and similar
ok {test-number} - with 1 message: 'ContainerIsRandomAccess( array_int_a ) != ContainerIsRandomAccess( list_char_a )'
# Type conversions of RangeEquals and similar
ok {test-number} - array_int_a, RangeEquals( list_char_a ) for: { 1, 2, 3 } elements are { 1, 2, 3 }
# Type conversions of RangeEquals and similar
ok {test-number} - array_int_a, UnorderedRangeEquals( list_char_a ) for: { 1, 2, 3 } unordered elements are { 1, 2, 3 }
# Type conversions of RangeEquals and similar
ok {test-number} - vector_int_a, RangeEquals( vector_char_a ) for: { 1, 2, 3 } elements are { 1, 2, 3 }
# Type conversions of RangeEquals and similar
ok {test-number} - vector_int_a, UnorderedRangeEquals( vector_char_a ) for: { 1, 2, 3 } unordered elements are { 1, 2, 3 }
# Type conversions of RangeEquals and similar
ok {test-number} - vector_int_a, !RangeEquals( vector_char_b ) for: { 1, 2, 3 } not elements are { 1, 2, 2 }
# Type conversions of RangeEquals and similar
ok {test-number} - vector_int_a, !UnorderedRangeEquals( vector_char_b ) for: { 1, 2, 3 } not unordered elements are { 1, 2, 2 }
# Type conversions of RangeEquals and similar
ok {test-number} - a, !RangeEquals( b ) for: { 1, 2, 3 } not elements are { 3, 2, 1 }
# Type conversions of RangeEquals and similar
ok {test-number} - a, UnorderedRangeEquals( b ) for: { 1, 2, 3 } unordered elements are { 3, 2, 1 }
# Type conversions of RangeEquals and similar
ok {test-number} - vector_a, RangeEquals( array_a_plus_1, close_enough ) for: { 1, 2, 3 } elements are { 2, 3, 4 }
# Type conversions of RangeEquals and similar
ok {test-number} - vector_a, UnorderedRangeEquals( array_a_plus_1, close_enough ) for: { 1, 2, 3 } unordered elements are { 2, 3, 4 }
# Unexpected exceptions can be translated # Unexpected exceptions can be translated
not ok {test-number} - unexpected exception with message: '3.14' not ok {test-number} - unexpected exception with message: '3.14'
# Upcasting special member functions # Upcasting special member functions
@@ -3418,6 +3468,70 @@ ok {test-number} - mocked.m_derefed[2] for: true
ok {test-number} - !(mocked.m_derefed[3]) for: !false ok {test-number} - !(mocked.m_derefed[3]) for: !false
# Usage of NoneTrue range matcher # Usage of NoneTrue range matcher
ok {test-number} - !(mocked.m_derefed[4]) for: !false ok {test-number} - !(mocked.m_derefed[4]) for: !false
# Usage of RangeEquals range matcher
ok {test-number} - empty_vector, RangeEquals( empty_vector ) for: { } elements are { }
# Usage of RangeEquals range matcher
ok {test-number} - empty_vector, !RangeEquals( non_empty_vector ) for: { } not elements are { 1 }
# Usage of RangeEquals range matcher
ok {test-number} - non_empty_vector, !RangeEquals( empty_vector ) for: { 1 } not elements are { }
# Usage of RangeEquals range matcher
ok {test-number} - non_empty_array, RangeEquals( non_empty_array ) for: { 1 } elements are { 1 }
# Usage of RangeEquals range matcher
ok {test-number} - array_a, RangeEquals( array_a ) for: { 1, 2, 3 } elements are { 1, 2, 3 }
# Usage of RangeEquals range matcher
ok {test-number} - array_a, !RangeEquals( array_b ) for: { 1, 2, 3 } not elements are { 2, 2, 3 }
# Usage of RangeEquals range matcher
ok {test-number} - array_a, !RangeEquals( array_c ) for: { 1, 2, 3 } not elements are { 1, 2, 2 }
# Usage of RangeEquals range matcher
ok {test-number} - vector_a, !RangeEquals( vector_b ) for: { 1, 2, 3 } not elements are { 1, 2, 3, 4 }
# Usage of RangeEquals range matcher
ok {test-number} - vector_a, RangeEquals( vector_a_plus_1, close_enough ) for: { 1, 2, 3 } elements are { 2, 3, 4 }
# Usage of RangeEquals range matcher
ok {test-number} - vector_a, !RangeEquals( vector_b, close_enough ) for: { 1, 2, 3 } not elements are { 3, 3, 4 }
# Usage of RangeEquals range matcher
ok {test-number} - needs_adl1, RangeEquals( needs_adl2 ) for: { 1, 2, 3, 4, 5 } elements are { 1, 2, 3, 4, 5 }
# Usage of RangeEquals range matcher
ok {test-number} - needs_adl1, RangeEquals( needs_adl3, []( int l, int r ) { return l + 1 == r; } ) for: { 1, 2, 3, 4, 5 } elements are { 2, 3, 4, 5, 6 }
# Usage of RangeEquals range matcher
ok {test-number} - mocked1, !RangeEquals( arr ) for: { 1, 2, 3, 4 } not elements are { 1, 2, 4, 4 }
# Usage of RangeEquals range matcher
ok {test-number} - mocked1.m_derefed[0] for: true
# Usage of RangeEquals range matcher
ok {test-number} - mocked1.m_derefed[1] for: true
# Usage of RangeEquals range matcher
ok {test-number} - mocked1.m_derefed[2] for: true
# Usage of RangeEquals range matcher
ok {test-number} - !(mocked1.m_derefed[3]) for: !false
# Usage of RangeEquals range matcher
ok {test-number} - mocked1, RangeEquals( arr ) for: { 1, 2, 3, 4 } elements are { 1, 2, 3, 4 }
# Usage of RangeEquals range matcher
ok {test-number} - mocked1.m_derefed[0] for: true
# Usage of RangeEquals range matcher
ok {test-number} - mocked1.m_derefed[1] for: true
# Usage of RangeEquals range matcher
ok {test-number} - mocked1.m_derefed[2] for: true
# Usage of RangeEquals range matcher
ok {test-number} - mocked1.m_derefed[3] for: true
# Usage of UnorderedRangeEquals range matcher
ok {test-number} - empty_vector, UnorderedRangeEquals( empty_vector ) for: { } unordered elements are { }
# Usage of UnorderedRangeEquals range matcher
ok {test-number} - empty_vector, !UnorderedRangeEquals( non_empty_vector ) for: { } not unordered elements are { 1 }
# Usage of UnorderedRangeEquals range matcher
ok {test-number} - non_empty_vector, !UnorderedRangeEquals( empty_vector ) for: { 1 } not unordered elements are { }
# Usage of UnorderedRangeEquals range matcher
ok {test-number} - non_empty_array, UnorderedRangeEquals( non_empty_array ) for: { 1 } unordered elements are { 1 }
# Usage of UnorderedRangeEquals range matcher
ok {test-number} - array_a, UnorderedRangeEquals( array_a ) for: { 1, 2, 3 } unordered elements are { 1, 2, 3 }
# Usage of UnorderedRangeEquals range matcher
ok {test-number} - array_a, !UnorderedRangeEquals( array_b ) for: { 1, 2, 3 } not unordered elements are { 2, 2, 3 }
# Usage of UnorderedRangeEquals range matcher
ok {test-number} - vector_a, !UnorderedRangeEquals( vector_b ) for: { 1, 2, 3 } not unordered elements are { 1, 2, 3, 4 }
# Usage of UnorderedRangeEquals range matcher
ok {test-number} - vector_a, UnorderedRangeEquals( vector_a_plus_1, close_enough ) for: { 1, 10, 20 } unordered elements are { 11, 21, 2 }
# Usage of UnorderedRangeEquals range matcher
ok {test-number} - vector_a, !UnorderedRangeEquals( vector_b, close_enough ) for: { 1, 10, 21 } not unordered elements are { 11, 21, 3 }
# Usage of UnorderedRangeEquals range matcher
ok {test-number} - needs_adl1, UnorderedRangeEquals( needs_adl2 ) for: { 1, 2, 3, 4, 5 } unordered elements are { 1, 2, 3, 4, 5 }
# Usage of the SizeIs range matcher # Usage of the SizeIs range matcher
ok {test-number} - empty_vec, SizeIs(0) for: { } has size == 0 ok {test-number} - empty_vec, SizeIs(0) for: { } has size == 0
# Usage of the SizeIs range matcher # Usage of the SizeIs range matcher
@@ -3594,6 +3708,10 @@ ok {test-number} - encode( "[\x01]" ) == "[\\x01]" for: "[\x01]" == "[\x01]"
ok {test-number} - encode( "[\x7F]" ) == "[\\x7F]" for: "[\x7F]" == "[\x7F]" ok {test-number} - encode( "[\x7F]" ) == "[\\x7F]" for: "[\x7F]" == "[\x7F]"
# XmlWriter writes boolean attributes as true/false # XmlWriter writes boolean attributes as true/false
ok {test-number} - stream.str(), ContainsSubstring(R"(attr1="true")") && ContainsSubstring(R"(attr2="false")") for: "<?xml version="1.0" encoding="UTF-8"?> <Element1 attr1="true" attr2="false"/> " ( contains: "attr1="true"" and contains: "attr2="false"" ) ok {test-number} - stream.str(), ContainsSubstring(R"(attr1="true")") && ContainsSubstring(R"(attr2="false")") for: "<?xml version="1.0" encoding="UTF-8"?> <Element1 attr1="true" attr2="false"/> " ( contains: "attr1="true"" and contains: "attr2="false"" )
# a succeeding test can still be skipped
ok {test-number} -
# a succeeding test can still be skipped
ok {test-number} - # SKIP
# analyse no analysis # analyse no analysis
ok {test-number} - analysis.mean.point.count() == 23 for: 23.0 == 23 ok {test-number} - analysis.mean.point.count() == 23 for: 23.0 == 23
# analyse no analysis # analyse no analysis
@@ -3764,6 +3882,12 @@ ok {test-number} - convertToBits( -0. ) == ( 1ULL << 63 ) for: 92233720368547758
ok {test-number} - convertToBits( std::numeric_limits<float>::denorm_min() ) == 1 for: 1 == 1 ok {test-number} - convertToBits( std::numeric_limits<float>::denorm_min() ) == 1 for: 1 == 1
# convertToBits # convertToBits
ok {test-number} - convertToBits( std::numeric_limits<double>::denorm_min() ) == 1 for: 1 == 1 ok {test-number} - convertToBits( std::numeric_limits<double>::denorm_min() ) == 1 for: 1 == 1
# dynamic skipping works with generators
ok {test-number} - # SKIP 'skipping because answer = 41'
# dynamic skipping works with generators
ok {test-number} -
# dynamic skipping works with generators
ok {test-number} - # SKIP 'skipping because answer = 43'
# empty tags are not allowed # empty tags are not allowed
ok {test-number} - Catch::TestCaseInfo("", { "test with an empty tag", "[]" }, dummySourceLineInfo) ok {test-number} - Catch::TestCaseInfo("", { "test with an empty tag", "[]" }, dummySourceLineInfo)
# erfc_inv # erfc_inv
@@ -3782,6 +3906,22 @@ ok {test-number} -
ok {test-number} - ok {test-number} -
# even more nested SECTION tests # even more nested SECTION tests
ok {test-number} - ok {test-number} -
# failed assertions before SKIP cause test case to fail
not ok {test-number} - 3 == 4
# failed assertions before SKIP cause test case to fail
ok {test-number} - # SKIP
# failing for some generator values causes entire test case to fail
not ok {test-number} - explicitly
# failing for some generator values causes entire test case to fail
ok {test-number} - # SKIP
# failing for some generator values causes entire test case to fail
not ok {test-number} - explicitly
# failing for some generator values causes entire test case to fail
ok {test-number} - # SKIP
# failing in some unskipped sections causes entire test case to fail
ok {test-number} - # SKIP
# failing in some unskipped sections causes entire test case to fail
not ok {test-number} - explicitly
# is_unary_function # is_unary_function
ok {test-number} - with 1 message: 'Catch::Clara::Detail::is_unary_function<decltype(unary1)>::value' ok {test-number} - with 1 message: 'Catch::Clara::Detail::is_unary_function<decltype(unary1)>::value'
# is_unary_function # is_unary_function
@@ -3890,6 +4030,8 @@ ok {test-number} - a != b for: 1 != 2
ok {test-number} - b != a for: 2 != 1 ok {test-number} - b != a for: 2 != 1
# nested SECTION tests # nested SECTION tests
ok {test-number} - a != b for: 1 != 2 ok {test-number} - a != b for: 1 != 2
# nested sections can be skipped dynamically at runtime
ok {test-number} - # SKIP
# non streamable - with conv. op # non streamable - with conv. op
ok {test-number} - s == "7" for: "7" == "7" ok {test-number} - s == "7" for: "7" == "7"
# non-copyable objects # non-copyable objects
@@ -4054,12 +4196,20 @@ ok {test-number} - Timing.elapsed >= time for: 128 ns >= 100 ns
ok {test-number} - Timing.result == Timing.iterations + 17 for: 145 == 145 ok {test-number} - Timing.result == Timing.iterations + 17 for: 145 == 145
# run_for_at_least, int # run_for_at_least, int
ok {test-number} - Timing.iterations >= time.count() for: 128 >= 100 ok {test-number} - Timing.iterations >= time.count() for: 128 >= 100
# sections can be skipped dynamically at runtime
ok {test-number} -
# sections can be skipped dynamically at runtime
ok {test-number} - # SKIP
# sections can be skipped dynamically at runtime
ok {test-number} -
# send a single char to INFO # send a single char to INFO
not ok {test-number} - false with 1 message: '3' not ok {test-number} - false with 1 message: '3'
# sends information to INFO # sends information to INFO
not ok {test-number} - false with 2 messages: 'hi' and 'i := 7' not ok {test-number} - false with 2 messages: 'hi' and 'i := 7'
# shortened hide tags are split apart # shortened hide tags are split apart
ok {test-number} - testcase.tags, VectorContains( Tag( "magic-tag" ) ) && VectorContains( Tag( "."_catch_sr ) ) for: { {?}, {?} } ( Contains: {?} and Contains: {?} ) ok {test-number} - testcase.tags, VectorContains( Tag( "magic-tag" ) ) && VectorContains( Tag( "."_catch_sr ) ) for: { {?}, {?} } ( Contains: {?} and Contains: {?} )
# skipped tests can optionally provide a reason
ok {test-number} - # SKIP 'skipping because answer = 43'
# splitString # splitString
ok {test-number} - splitStringRef("", ','), Equals(std::vector<StringRef>()) for: { } Equals: { } ok {test-number} - splitStringRef("", ','), Equals(std::vector<StringRef>()) for: { } Equals: { }
# splitString # splitString
@@ -4142,6 +4292,8 @@ ok {test-number} - strlen(std::get<0>(data)) == static_cast<size_t>(std::get<1>(
ok {test-number} - testcase.tags.size() == 1 for: 1 == 1 ok {test-number} - testcase.tags.size() == 1 for: 1 == 1
# tags with dots in later positions are not parsed as hidden # tags with dots in later positions are not parsed as hidden
ok {test-number} - testcase.tags[0].original == "magic.tag"_catch_sr for: magic.tag == magic.tag ok {test-number} - testcase.tags[0].original == "magic.tag"_catch_sr for: magic.tag == magic.tag
# tests can be skipped dynamically at runtime
ok {test-number} - # SKIP
# thrown std::strings are translated # thrown std::strings are translated
not ok {test-number} - unexpected exception with message: 'Why would you throw a std::string?' not ok {test-number} - unexpected exception with message: 'Why would you throw a std::string?'
# toString on const wchar_t const pointer returns the string contents # toString on const wchar_t const pointer returns the string contents
@@ -4314,5 +4466,5 @@ ok {test-number} - q3 == 23. for: 23.0 == 23.0
ok {test-number} - ok {test-number} -
# xmlentitycheck # xmlentitycheck
ok {test-number} - ok {test-number} -
1..2159 1..2237

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