Commit Graph
89 Commits
Author SHA1 Message Date
Martin Hořeňovský 8582805f54 Support TEST_{PREFIX,SUFFIX} with leading/trailing whitespace
Closes #2149
2026-08-20 16:24:18 +02:00
Martin Hořeňovský 97ec4e8e2e catch_discover_tests: Escape test-invariant parts of CTest script only once
Previously, the `catch_discover_tests` would prepare the entire CTest
command (e.g. `add_test(...)` or `set_tests_properties(...)`) first, and
then escape it when finished. However, this caused lot of the command args
to be escaped over and over again (e.g. executable name or Catch2's reporter
args), for no reason, as they were always the same, and thus their escaping
was always the same.

Until recently, the performance overhead didn't matter as there were many
spots which had quadratic runtime in number of tests. However, the recent
refactorings fixed these, and this commit now improves the throughput by
10-20%.

Also extended the benchmarked COUNTS in `benchmark_discovery.py`,
because the performance is now good enough that it is reasonable
to benchmark 16k tests.
2026-08-10 11:53:22 +02:00
Martin Hořeňovský 0136276e15 Avoid n**2 runtime when creating list of tests in catch_discover_tests
This was another place where the script triggered the quadratic runtime
from calling `string(APPEND` (or `list(APPEND`) repeatedly. As in
60c8b87, we avoid this by flushing the test list into a file every
50kB of text input.

As the string with the test list never grew quite as much as the
string that contains all the test definitions, this only provides
significant savings for high number of tests. It starts being
properly measurable around 4k tests at ~100ms, but grows to ~4s at
32k tests.
2026-08-10 10:36:04 +02:00
Martin Hořeňovský 630840c500 Fix <target>_TESTS variable generated by catch_discover_tests
There were 2 separate bugs, one recently added and one ancient
(since roughly the first version of the registration script).

1) The recent refactoring of how the JSON output from Catch2 is
   parsed caused shadowing between the variable containing the
   per-test JSON fragments and the accumulator of test names for
   <target>_TESTS variable. This led to the variable containing
   both the names and the JSON fragments, and thus being completely
   wrong.

2) The test name accumulation has never accounted for characters
   that need escaping to be present in a CMake list. This means
   that e.g. test names with semicolon in them would end up with
   two elements in the test list.

Both of these are now fixed, at the cost of extra complexity and
my sanity as I had to learn more about CMake escaping rules.

(CMake escaping rules are dumb)
2026-08-10 00:17:26 +02:00
Martin Hořeňovský 4cde128517 JSONReporter considers verbosity when listing tests
* Quiet verbosity provides just the test names
* Normal verbosity adds tags
* High verbosity add the source location of the tests

Listing tests with the quiet verbosity results in about 1/4 of the
previous output, which leads to measurably faster execution of
`catch_discover_tests` when it does not need tags for labels.
(If it does need tags, the output is about 1/2 of previous).
2026-08-08 00:05:18 +02:00
Martin Hořeňovský 0b4d7a5a16 JSONReporter's listTests only lists class-name if it is non-empty 2026-08-07 23:07:46 +02:00
Martin Hořeňovský 8b08d4d795 v3.15.3 2026-07-26 22:19:31 +02:00
Martin Hořeňovský 1079da4c5f Avoid quadratic JSON array parse behaviour in catch_discover_tests
Using CMake's `string(JSON` to parse JSON array leads to quadratic
running time in number of tests, see https://gitlab.kitware.com/cmake/cmake/-/work_items/27985

This leads to _terrible_ runtime for `catch_discover_tests` when called
on binaries with lot of tests (1k+). To get reasonable runtimes, we have
to avoid using `string(JSON` to parse out the individual test objects
from the array with all tests.

This commit replaces the sane approach of using real JSON parser with
a set of terrible hacks, where we use CMake's string APIs to split the
JSON array on what looks like object boundary (`}<ws>*,<ws>*{`), and then
checking whether the resulting thing can be parsed as JSON object. If not,
we append the next piece and check again. And again, and again, until we
get a proper JSON object.

This is all around a hilariously terrible idea, however:

1) It works in practice for all tested inputs.
2) It improves the time it takes to run `catch_discover_tests` on binary
   with 1k tests from 4.2s to 1.1s and 2k tests from 16s to 3.9s.
2026-07-26 19:51:58 +02:00
Martin Hořeňovský 60c8b87829 Avoid n^2 behaviour when appending script commands in catch_discover_tests
Repeatedly calling `string(APPEND` on the same destination string
leads to quadratic running time. We avoid this by flushing the CTest
script into a file periodically, currently every 50kB of text.

This can cause _slight_ slowdown just around the flush boundary (each
file write is quite expensive, so if we flush just before the last test
is written, it hurts), but it avoids terrible performance for large
test suites.

The performance is roughly equal at 500 tests to discover, and clearly
wins at more; for 1/2/4/8 k tests, the improvements are 0.3/1.6/6.4/27 s.
2026-07-26 15:50:33 +02:00
Martin Hořeňovský 64a551e2e7 Optimize adding test commands in catch_discover_tests
The previous approach was for `add_command` to behave as append function
via concatenating the command string internally and then saving it into
`PARENT_SCOPE`. Because this in practice ended up meaning concatenating
a copy of the string inside the function and then overwriting the string
outside the function, the performance was lacking.

The new approach is for `prepare_command` to only escape & return the
command from single call, and the caller is responsible for concatenating
the result. Since the actual concatenation no longer crosses function
scope boundaries, the performance is much better, even though the scaling
is still quadratic.

The new approach only takes 1/4-1/5 of the time, saving ~1s at 1k tests,
4.5s at 2k tests and 19s at 4k tests.
2026-07-26 15:50:31 +02:00
Martin Hořeňovský 2b971368dd Determinize the test registration order in catch_discover_tests 2026-07-26 15:23:39 +02:00
Phil Nash eb431764b4 Document that DISCOVERY_MODE PRE_TEST should be used with catch_discover_tests when used with XCode.
This addresses https://github.com/catchorg/Catch2/issues/2411 by making the "workaround" the official approach and is consistent with how gtest and cmake deal with the same situation.
2026-07-22 20:50:17 +02:00
Manuel Knörle ae5d271da2 Remove debug message for environment variable check 2026-07-15 11:19:22 +02:00
Nikolay Baklicharov a15f718c82 Optimize JSON parsing in catch_discover_tests() 2026-07-08 10:29:59 +02:00
Martin Hořeňovský 191fa38c9b v3.15.2 2026-07-07 20:44:33 +02:00
Martin Hořeňovský 9ec44dd62b catch_discover_tests uses tempfile to retrieve JSON from the binary
This allows it to deal with badly behaved code, where 3rd party
dependencies write into stdout during global construction.

Closes #3162
Closes #3166
2026-07-04 16:36:05 +02:00
Martin Hořeňovský bcfb10e498 v3.15.1 2026-06-14 10:57:30 +02:00
Martin Hořeňovský 6ee0826dca v3.15.0 2026-05-12 13:16:46 +02:00
Martin Hořeňovský b670de4fe1 v3.14.0 2026-04-05 15:05:38 +02:00
Sung, Po Han f4e83daa18 Fix catch_discover_tests PRE_TEST failure with zero discoverable tests
When using catch_discover_tests() with DISCOVERY_MODE PRE_TEST and a
multi-config generator (e.g. Ninja Multi-Config), if a test target has
zero discoverable tests (e.g. all tests tagged with [.]), ctest fails:

  CMake Error: include could not find requested file:
    .../test-hidden-b12d07c_tests-Release.cmake

The early return added in #2962 (76f70b14) correctly prevented a JSON
parsing crash for zero tests, but skipped writing the ctest file. The
PRE_TEST include script unconditionally includes this file, so the
missing file causes a hard error that aborts all test discovery.

Write an empty file before returning early so the include always
succeeds.
2026-04-02 10:24:46 +02:00
Martin Hořeňovský 29c9844f68 v3.13.0 2026-02-15 22:55:48 +01:00
Martin Hořeňovský 88abf9bf32 v3.12.0 2025-12-28 22:31:54 +01:00
Martin Hořeňovský b3fb4b9fea v3.11.0 2025-09-30 10:54:31 +02:00
Martin Hořeňovský 25319fd304 v3.10.0 2025-08-25 21:30:21 +02:00
Martin Hořeňovský 644821ce28 v3.9.1 2025-08-09 00:30:23 +02:00
Martin Hořeňovský fee81626d2 v3.9.0 2025-07-24 22:01:46 +02:00
Chris Thrasher 8cfca70ae8 Fix formatting of CMake files
2 spaces seems to be the more common indentation level so that's what
I unified around.
2025-04-26 10:38:36 -06:00
Chris Thrasher 2b60af89e2 v3.8.1 2025-04-08 12:40:18 -06:00
Chris Thrasher 76f70b1403 Fix bug where catch_discover_tests fails when no TEST_CASEs are present 2025-03-12 14:03:56 -06:00
Martin Hořeňovský 914aeecfe2 v3.8.0 2025-01-06 00:41:45 +01:00
Martin Hořeňovský 7d7b2f89f2 Support adding test tags as CTest labels in catch_discover_tests
We also bump the minimum CMake version to 3.20 as per #2943
2025-01-05 20:02:00 +01:00
Holger Kaelberer 0321d2fce3 Catch.cmake: Remove redundant CTEST_FILE param 2024-11-22 11:05:50 +01:00
Martin Hořeňovský fa43b77429 v3.7.1 2024-09-17 10:45:43 +02:00
Martin Hořeňovský 79f2d66ea3 Use SKIP_RETURN_CODE test property in catch_discover_tests
I also added `SKIP_IS_FAILURE` option to the `catch_discover_tests`
function, to allow users to get back the old behaviour.

Closes #2873
2024-09-17 09:35:43 +02:00
Martin Hořeňovský 31588bb4f5 v3.7.0 2024-08-14 12:05:21 +02:00
Martin Hořeňovský a579b5f640 Properly handle prepending user-specified paths to DYLD_FRAMEWORK_PATH 2024-08-13 23:05:21 +02:00
Chien-Yu Lin 1538be67cb Respect path order of DL_PATHS in catch_discover_tests function 2024-08-13 22:23:16 +02:00
Andy Phillips 85b7f3d6ab Add optional argument to catch_discover_tests to set DYLD_FRAMEWORK_PATH (#2880)
* Added optional argument to catch_discover_tests to set the DYLD_FRAMEWORK_PATH environment variable on Apple platforms.
2024-07-22 19:25:24 +02:00
Martin Hořeňovský 4e8d92bf02 v3.6.0 2024-05-05 20:58:18 +02:00
Martin Hořeňovský b5373dadca v3.5.4 2024-04-10 12:05:46 +02:00
Cristian Le 202bdee977 Fix TEST_DL_PATHS to be multi-args
Signed-off-by: Cristian Le <cristian.le@mpsd.mpg.de>
2024-03-26 18:04:17 +01:00
Chris Thrasher 792c3b7549 Stop repeating conditional in endif()
This is not necessary so we can remove it. Most conditionals already
omit this anyways.
2024-03-12 22:55:12 +01:00
Martin Hořeňovský 8ac8190e49 v3.5.3 2024-03-01 22:07:10 +01:00
Martin Hořeňovský 05e10dfccc v3.5.2 2024-01-15 14:13:53 +01:00
Chris Thrasher 05786fa7ec Remove redundant destructors
Classes will automatically inherit the virtual-ness of their base
class destructors. If the base class already has a virtual
destructor and the derived class needs default destructor semantics
then the derived class can omit defining the destructor in favor of
the compiler automatically defining it.

This has an additional benefit of reenabling move semantics. The
presence of a user-specified destructor automatically disables move
operations.
2024-01-14 23:33:51 +01:00
Martin Hořeňovský f981c9cbca v3.5.1 2023-12-31 15:15:04 +01:00
Martin Hořeňovský 53d0d913a4 v3.5.0 2023-12-11 00:55:40 +01:00
Holger KaelbererandHolger Kaelberer 7b793314e5 Catch.cmake: Support CMake multi-config with PRE_TEST discovery mode (#2739)
Closes #2746 

---------

Co-authored-by: Holger Kaelberer <Holger.Kaelberer@bmw.de>
2023-09-25 19:40:35 +02:00
Ilya Arzhannikov db495acdbb correct argument references in CatchAddTests.cmake 2023-09-20 15:47:11 +02:00
Martin Hořeňovský 6e79e682b7 v3.4.0 2023-07-13 13:37:30 +02:00