164 Commits

Author SHA1 Message Date
Martin Hořeňovský 47200ddbee Rework internals of CATCH_REGISTER_ENUM
The old internals reached into the global hub to stash the allocation(s)
for enum value -> string value there, then kept around a potentially
invalid (in case the hub was cleaned up) reference into it, going through
whole bunch of virtual dispatch in the process.

The new internals just store the data in a static variable inside the
`StringMaker` specialization. This avoids potential lifetime issues,
avoids all virtual dispatch and (almost) reduces the include bloat in
the main header path.

The reason for (almost) there is that for full include correctness,
`EnumInfo` needs `<utility>` include for `std::pair`. However, this brings
in things like `std::relops`, because the std headers in C++ are dumb.
As this was not included before, and instead we relied on `std::pair`
existing in an internal stdlib header that we transitively included, the
full include size ends up bigger than before.
2026-04-08 12:57:09 +02:00
Martin Hořeňovský 57f738b380 JUnit reporter output single failed assertion node per test case
Ideally JUnit tools would handle multiple failures per test case,
but they don't, so here we are.

Closes #1919
2026-04-04 15:12:56 +02:00
Martin Hořeňovský 56024c04e4 More tests for MapGenerator 2026-02-15 21:53:10 +01:00
Martin Hořeňovský 056e4fe88d MapGenerator only calls mapping function if the result is used
Previously the mapping was eager on construction and calls to
`next()`. This was fine when generators were always exhausted fully,
but with the new generator filtering, we might not want to call
the map function eagerly; rather we want to call it only once,
after the generator is moved to the target element.
2026-02-15 20:44:21 +01:00
Martin Hořeňovský 3a0cf7e75f Support filtering on both sections and generators (#3069)
Not being able to filter generators to specific element has been regularly
causing problems. It was possible to use a dynamic section to run tests
for specific element in a generator, at least if the element had a nice
string representation, but the test case would still run once per element
in the generator.

With this change, it is possible to have the generator return only one
specific element, and do so based on the index, rather than the string
representation of the element. This enables simple debugging of tests
that fail for specific generator element.
2026-02-15 20:27:15 +01:00
Martin Hořeňovský daadf42a0e Add --warn InfiniteGenerators 2026-02-10 09:37:19 +01:00
Martin Hořeňovský d079ee13ab Allow generators to declare themselves (infinite)
This will be useful later to implement warning on infinitely
running `GENERATE` expressions.
2026-02-10 09:37:15 +01:00
Martin Hořeňovský 024aec9729 Add efficient skip forward to Values, Map and Take generators 2026-01-12 22:39:59 +01:00
Martin Hořeňovský 9eca713a1f Add option to skip forward to the generator interface 2026-01-12 16:58:15 +01:00
Martin Hořeňovský 44c597f074 Add Concat generator for combining multiple generators 2026-01-12 14:27:49 +01:00
Martin Hořeňovský 2580eadc42 Add UNSCOPED_CAPTURE
Closes #2954
Closes #3010
2026-01-11 14:53:08 +01:00
qerased b66b89374e Add validation for --benchmark-samples to prevent crash with zero value (#3056)
* Add validation for --benchmark-samples to prevent crash with zero samples
* Add automated test for benchmark samples validation
* Update baselines for benchmark-samples validation
* Add missing test for benchmark samples validation

---------

Co-authored-by: Chan Aung <chan@Thinkpad.localdomain>
2026-01-02 23:15:13 +01:00
Martin Hořeňovský 985a3f4460 Fix lazy removal of unscoped messages also removing still valid msgs 2025-11-30 14:30:19 +01:00
Szapi 85c4bad86b Forbid deducing reference types for m_predicate in FilterGenerator (#3005)
Forbid deducing reference types for m_predicate in FilterGenerator to prevent dangling references.
This is needed for out-of-line predicates to work correctly instead of undefined behavior or crashes.

---------

Co-authored-by: Tek Mate <mate.tek@evosoft.com>
2025-08-23 21:55:38 +02:00
Martin Hořeňovský 03c62cdf2e Add tests for comparing & stringifying volatile pointers 2025-08-08 00:02:33 +02:00
Martin Hořeňovský 9b3f508a1b Cleanup WIP changes from last commit 2025-08-02 10:21:41 +02:00
Martin Hořeňovský c5e0ef4e67 Catch exceptions from StringMakers inside Detail::stringify
This stops tests failing falsely if the assertion passed, but the
stringification itself failed as the assertion was sent to the reporter.

I don't think that stringification should be fallible, but the
overhead in compilation ended up being small enough (<0.5% on `SelfTest`)
that it might be worth implementing, in case there is more users
with weird `StringMaker`s than just MongoDB.

Closes #2980
2025-08-02 10:11:52 +02:00
Martin Hořeňovský 17fe5eaa5c Fix StringMaker for time_point<system_clock> with non-default duration
Fixes #2685
2025-08-02 08:31:34 +02:00
Martin Hořeňovský ccabd4de89 Add enum types to what is captured by value by default
As it turns out, enums can be used to declare bitfields, and we
cannot form a reference to a bitfield in the cpature. Thus, we add
`std::is_enum` as a criteria to the default for `capture_by_value`,
so that enum-based bitfields are also captured by value and thus
decomposable.

Closes #3001
2025-07-30 20:20:38 +02:00
Martin Hořeňovský d547cae549 Fix bad error reporting for nested exceptions in default configuration
Bad handling of `TestFailureException` when translating unexpected
exceptions inside assertion macros led to the unexpected exceptions
handling erroring out through throwing the same exception again.

This was then backstopped by the machinery for handling uncaught
exceptions from assertions, which is normally used by the
`CATCH_CONFIG_FAST_COMPILE` machinery, where we assume that it can
only be invoked because the assertion macros are not configured to
catch assertions.

Closes #1292
2025-07-27 21:41:02 +02:00
Martin Hořeňovský 10aef62f21 Regularize scoped message lifetime to only consider the object's scope
This means that:
1) Scoped messages are always removed at the end of their scope,
   even if the scope ended due to an exception.
2) Scoped messages outlive section end, if that section's scope is
   enclosed in their own.

Previously neither of these were true, which has led to a number
of surprising behaviour, where e.g. this:
```cpp
TEST_CASE() {
    try {
        INFO( "some info" );
        throw std::runtime_error( "ex" );
    } catch (std::exception const&) {}

    REQUIRE( false );
}
```
would print "some info" as the message for the assertion, while this:
```cpp
TEST_CASE() {
    INFO("Hello");
    SECTION("dummy") {}
    REQUIRE(false);
}
```
would not print out "Hello" as the message for the assertion.

This had an underlying reason, in that it was trying to helpfully
keep the messages around in case of unexpected exceptions, so that
code like this:
```cpp
TEST_CASE() {
    auto [input, expected] = GENERATE(...);
    CAPTURE(input);
    auto result = transform(input); // throws
    REQUIRE(result == expected);
}
```
would report the value of `input` when `transform` throws. However,
it was surprising in practice and was causing various issues around
handling of messages in other cases.

Closes #1759
Closes #2019
Closes #2959
2025-07-21 21:50:47 +02:00
Martin Hořeňovský 0e8112a762 Only track the last line info in RunContext
There were only two places where we used the full `AssertionInfo`
instance in `m_lastAssertionInfo`:
1) when reporting unexpected exception from running a test case
2) when reporting fatal error

because in those two places we do not have access to a real
instance of `AssertionInfo`, but we still need to send one to the
reporters. As a bonus, in both of these places we were already
constructing a fake-ish assertion info, by using the last encountered
source location, but dummying out the other information.

Instead, we only keep track of the last encountered source location,
and construct the dummy `AssertionInfo` on-demand.

This finishes the set of refactoring around `m_lastAssertionInfo`
in `RunContext` and improves the performance of running assertions
by ~5% in both Debug and Release mode.

--------------

Note that this change also causes small difference in output. It
could be avoided by having an invalidation flag and tracking where
the information would be invalidated before, but the difference
includes more precise line location for unexpected errors (both
exceptions and fatals), so I prefer the new output.
2025-07-17 11:27:03 +02:00
Martin Hořeňovský b9c018b38a Use template variables for our trait-likes in Clara 2025-07-15 11:49:39 +02:00
Clement Courbet 2de12cb05f Allow using only types in TEMPLATE_TEST_CASE_SIG. (#2995)
Right now `TEMPLATE_TEST_CASE_SIG` fails to compile when the signature contains only types:

```
TEMPLATE_TEST_CASE_SIG(
  "TemplateTestSig: compiles with two type parameters",
  "[template][onlytypes]",
  ((typename U, typename V), U, V), (int,int)) {}
```

The trick is to resolve the ambiguity between the two overloads of
`get_wrapper` (`TypeList` and `Nttp`) by making one match more strongly.
We also need to allow `reg_test` to register more than one type.

Add unit tests.

Fixes #2680

---------

Co-authored-by: Martin Hořeňovský <martin.horenovsky@gmail.com>
2025-07-08 14:26:25 +02:00
Chris Thrasher 4c93a595a1 Fix typos 2025-04-26 22:46:42 -06:00
Thomas Braun 506276c592 Fix wrong reference to REGISTER_ENUM
This was renamed to CATCH_REGISTER_ENUM in 541f1ed1 (Only provide
CATCH_REGISTER_ENUM, 2019-04-21).
2024-11-12 23:29:54 +01:00
Stefan Haller 69d62abc9a Provide overloads for {Unordered}RangeEquals taking a std::initializer_list
This allows writing something like

  const auto v = calculateSomeVectorOfInts();
  CHECK_THAT(v, RangeEquals({1, 2, 3}));

Fixes #2915.
2024-10-14 21:02:03 +02:00
Mark Jansen 02d3304782 Fix bug in TokenStream parser
When presented with just '-' it would access the string at position [1]
2024-09-13 15:32:49 +02:00
Martin Hořeňovský fa306fc85e Improve performance of SonarQube reporter handling passing assertions
This mirrors the changes done to the JUnit reporter in commit
fe483c056d
2024-08-14 12:33:55 +02:00
Martin Hořeňovský fe483c056d Improve performance of JUnit reporter when handling passing assertions
This is done by no longer requiring all assertions to be seen
by the JUnit reporter. Since the JUnit reporter never outputs
all assertions, even with `-s`, the only difference from storing
passing assertions in the `CumulativeReporterBase` was some
bookkeeping in deciding which sections are relevant to the output.

Given `TEST_CASE` that just runs many passing assertions, e.g.

```
TEST_CASE( "PERFORMANCE_TEST_CASE", "[.]" ) {
    for (size_t i = 0; i < 1000'000'000; ++i) {
        REQUIRE( i == i );
    }
}
```

the new JUnit reporter will finish in 5:47, using up ~7.7 MB of RAM.
The old JUnit reporter would finish in 0:30, due to bad_alloc
after using up 14.5 GB of RAM (the system has 16 GB total).

If the total number of assertions is lowered to 10M, the old
implementation uses up ~7.1 GB of RAM and finishes in 12 minutes.
The new implementation still needs only ~7.7 MB of RAM, and finishes
in 4 minutes.

There is a slight downside in that the output is slightly different;
the new implementation will include the `TEST_CASE` level section
in output, even if it does not have its own assertion. In other words,
given a `TEST_CASE` like this

```
TEST_CASE( "JsonWriter", "[JSON][JsonWriter]" ) {
    std::stringstream stream;
    SECTION( "Newly constructed JsonWriter does nothing" ) {
        Catch::JsonValueWriter writer{ stream };
        REQUIRE( stream.str() == "" );
    }

    SECTION( "Calling writeObject will create an empty pair of braces" ) {
        { auto writer = Catch::JsonValueWriter{ stream }.writeObject(); }
        REQUIRE( stream.str() == "{\n}" );
    }
}
```

the new implementation will output 3 `testcase` tags, 2 for the explicit
 `SECTION`s with tests, and 1 for the top level section.

However, this can be worked-around if required, and the performance
improvement is such that it is worth changing the current output,
even if it needs to be fixed in the future.

Closes #2897
2024-08-13 19:13:03 +02:00
Keith Stockdale f7cd0ba051 TEST_CASE_PERSISTENT_FIXTURE: A new fixture macro for allowing persistent fixtures throughout a TEST_CASE (#2885)
This PR introduces a new `TEST_CASE` macro called `TEST_CASE_PERSISTENT_FIXTURE`. `TEST_CASE_PERSISTENT_FIXTURE` offers the same functionality as `TEST_CASE_METHOD` except for one difference. The object on which the test method is invoked is only created once for all invocations of the test case. The object is created just after the `testCaseStarting` event is broadcast and the object is destroyed just before the `testCaseEnding` event is broadcast.

The main motivation for this new functionality is to allow `TEST_CASE`s to do expensive setup and teardown once per `TEST_CASE`, without having to resort to abusing event listeners or static function variables with manual initialization.


Implements #1602

---------

Co-authored-by: Martin Hořeňovský <martin.horenovsky@gmail.com>
2024-08-05 17:01:41 +02:00
Martin Hořeňovský a654e4b038 Don't include numerically unstable tests in approvals 2024-04-30 19:21:27 +02:00
Martin Hořeňovský ef713582d2 Default StringMaker<FloatingPointType>::precision to max_digits10
`max_digits10` is the number of decimal digits that the type _can_
represent, in other words, the number of decimal digits needed to
disambiguate any two floating point numbers when serialized to
a string.
2024-04-30 17:18:48 +02:00
Ian Bell 53ddf37af4 Use Catch::StringMaker for output in WithinRelMatcher (#2846)
The WithinRelMatcher does not listen to the precision specification; it just naively pipes to stringstream. If you specify the precision, that has no impact on the outputted values when the match fails.

This fix makes the WithinRelMatcher listen to the precision (https://github.com/catchorg/Catch2/blob/devel/docs/tostring.md#floating-point-precision) specified by: Catch::StringMaker<float>::precision
2024-04-15 13:35:39 +02:00
Martin Jeřábek 4d8affc989 less copies and allocations in replaceInPlace 2024-03-01 21:24:45 +01:00
Martin Hořeňovský c3fd4eb17e Update outdated tests for stringifying characters
Previously the tests relied purely on output changes in approvals.
Now the stringification output is checked directly as part of the
unit tests.
2024-03-01 15:09:11 +01:00
Martin Hořeňovský ed9d672b5c Add uniform_integer_distribution 2023-12-10 19:53:39 +01:00
Martin Hořeňovský 9a1e73568c Add test showing literals and complex generators in one GENERATE 2023-12-10 18:32:45 +01:00
Martin Hořeňovský 733b901dd2 Fix special character escaping in JsonWriter 2023-11-14 23:35:22 +01:00
Beartama 7bf136b501 Add JSON reporter (#2706)
Co-authored-by: Martin Hořeňovský <martin.horenovsky@gmail.com>
2023-11-14 22:52:15 +01:00
Martin Hořeňovský 79d39a1954 Fix tests for C++23's multi-arg index operator
Closes #2744
2023-10-28 21:49:58 +02:00
Martin Hořeňovský 9c541ca72e Add test for multiple streaming parts in UNSCOPED_INFO 2023-09-17 10:44:31 +02:00
rosstang cd60a0301c Assert Info reset need to also reset result disposition to normal to handle uncaught exception correctly (#2723)
* AssertionEnd does not reset the assertion info yet. That is done after populateReaction. And reset assertion info would also reset the result disposition to normal, so that any uncaught exception would be reported as failure

* Approving test output changes due to added unit tests

* Unit tests to throw std::runtime_error instead of std::exception

* Add a unit test to test incomplete assertion handler

---------

Co-authored-by: Ross <ross.tang@gfo-x.com>
2023-08-07 22:07:31 +02:00
Martin Hořeňovský 0631b607ee Test & document SKIP in generator constructor
Closes #1593
2023-05-31 15:12:43 +02:00
Martin Hořeňovský a153fce724 Improve error messages for TEST_CASE tag parsing errors
Also removes a duplicated test case checking for empty tag error.

Related to #2650
2023-05-20 21:13:48 +02:00
Vertexwahn 46539b6d9b Fix spelling 2023-04-29 12:55:51 +02:00
Martin Hořeňovský 9a2a4eadc0 Bump xml-format-version in XML reporter 2023-04-10 21:59:50 +02:00
Martin Hořeňovský fb806da76f Add lineinfo to XML reporter output for INFO/WARN
Closes #1251
2023-04-10 16:32:07 +02:00
Martin Hořeňovský 6fbb3f0723 Add IsNaN matcher 2023-02-26 00:14:32 +01:00
Martin Hořeňovský cefa8fcf32 Enable use of UnorderedRangeEquals with iterator+sentinel pairs 2023-02-06 15:34:38 +01:00