Compare commits

...

9 Commits

Author SHA1 Message Date
Martin Hořeňovský
de6fe184a9 v2.13.4 2020-12-29 15:03:40 +01:00
Martin Hořeňovský
fe3dddcc6d Fix updateVersionPlaceholder when the placeholder starts the line 2020-12-29 15:02:25 +01:00
Reinhold Gschweicher
18ab353e55 Add deprecation warning in ParseAndCatchTests
Parsing C++ with regex in CMake is error prone and regularly leads to silently
dropped (not run) test cases.

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

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

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

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

contents of project specific helper `external/catch2/CMakeLists.txt`
```cmake
cmake_minimum_required (VERSION 3.1...${CMAKE_VERSION})
project(Catch2 LANGUAGES CXX VERSION 2.13.3)
add_library(Catch2 INTERFACE)
target_include_directories(Catch2
  INTERFACE
    $<BUILD_INTERFACE:${CMAKE_CURRENT_LIST_DIR}>
)
 # provide a namespaced alias for clients to 'link' against if catch is included as a sub-project
add_library(Catch2::Catch2 ALIAS Catch2)
include(contrib/Catch.cmake)
```
2020-12-17 18:50:04 +01:00
Martin Hořeňovský
fac517d571 Fix conan package build 2020-11-26 15:05:58 +01:00
Florian Berchtold
578f8b8006 Add bazel support 2020-11-18 21:37:12 +01:00
Deniz Evrenci
92f8b01dfa Add the static library Catch2WithMain
It should provide a shared impl for all targets that need to link
against Catch2's implementation. However, due to limitations of
C++ linking and Catch2's v2 implementation, this is only experimental
and might not work under some circumstances.
2020-11-18 21:37:10 +01:00
Martin Hořeňovský
dc7e705672 Small cleanups for the reworked test case order hashing 2020-11-17 21:08:33 +01:00
Sergio Losilla
3ba745552b Modified hash to make it more independent of the choice of test names. 2020-11-17 20:58:16 +01:00
16 changed files with 136 additions and 46 deletions

View File

@@ -5,6 +5,13 @@ load("@rules_cc//cc:defs.bzl", "cc_library")
cc_library( cc_library(
name = "catch2", name = "catch2",
hdrs = ["single_include/catch2/catch.hpp"], hdrs = ["single_include/catch2/catch.hpp"],
visibility = ["//visibility:public"],
includes = ["single_include/"], includes = ["single_include/"],
visibility = ["//visibility:public"],
)
cc_library(
name = "catch2_with_main",
srcs = ["src/catch_with_main.cpp"],
visibility = ["//visibility:public"],
deps = ["//:catch2"],
) )

View File

@@ -14,7 +14,7 @@ if (CMAKE_BINARY_DIR STREQUAL CMAKE_CURRENT_SOURCE_DIR)
endif() endif()
project(Catch2 LANGUAGES CXX VERSION 2.13.3) project(Catch2 LANGUAGES CXX VERSION 2.13.4)
# Provide path for scripts # Provide path for scripts
list(APPEND CMAKE_MODULE_PATH "${CMAKE_CURRENT_LIST_DIR}/CMake") list(APPEND CMAKE_MODULE_PATH "${CMAKE_CURRENT_LIST_DIR}/CMake")
@@ -103,6 +103,12 @@ endif()
# provide a namespaced alias for clients to 'link' against if catch is included as a sub-project # provide a namespaced alias for clients to 'link' against if catch is included as a sub-project
add_library(Catch2::Catch2 ALIAS Catch2) add_library(Catch2::Catch2 ALIAS Catch2)
# Hacky support for compiling the impl into a static lib
add_library(Catch2WithMain ${CMAKE_CURRENT_LIST_DIR}/src/catch_with_main.cpp)
target_link_libraries(Catch2WithMain PUBLIC Catch2)
add_library(Catch2::Catch2WithMain ALIAS Catch2WithMain)
# Only perform the installation steps when Catch is not being used as # Only perform the installation steps when Catch is not being used as
# a subproject via `add_subdirectory`, or the destinations will break, # a subproject via `add_subdirectory`, or the destinations will break,
# see https://github.com/catchorg/Catch2/issues/1373 # see https://github.com/catchorg/Catch2/issues/1373
@@ -121,7 +127,7 @@ if (NOT_SUBPROJECT)
# create and install an export set for catch target as Catch2::Catch # create and install an export set for catch target as Catch2::Catch
install( install(
TARGETS TARGETS
Catch2 Catch2 Catch2WithMain
EXPORT EXPORT
Catch2Targets Catch2Targets
DESTINATION DESTINATION

View File

@@ -9,7 +9,7 @@
[![Join the chat in Discord: https://discord.gg/4CWS9zD](https://img.shields.io/badge/Discord-Chat!-brightgreen.svg)](https://discord.gg/4CWS9zD) [![Join the chat in Discord: https://discord.gg/4CWS9zD](https://img.shields.io/badge/Discord-Chat!-brightgreen.svg)](https://discord.gg/4CWS9zD)
<a href="https://github.com/catchorg/Catch2/releases/download/v2.13.3/catch.hpp">The latest version of the single header can be downloaded directly using this link</a> <a href="https://github.com/catchorg/Catch2/releases/download/v2.13.4/catch.hpp">The latest version of the single header can be downloaded directly using this link</a>
## Catch2 is released! ## Catch2 is released!

View File

@@ -10,7 +10,7 @@ class CatchConan(ConanFile):
homepage = url homepage = url
license = "BSL-1.0" license = "BSL-1.0"
exports = "LICENSE.txt" exports = "LICENSE.txt"
exports_sources = ("single_include/*", "CMakeLists.txt", "CMake/*", "contrib/*") exports_sources = ("single_include/*", "CMakeLists.txt", "CMake/*", "contrib/*", "src/*")
generators = "cmake" generators = "cmake"
def package(self): def package(self):

View File

@@ -202,4 +202,5 @@ endfunction()
set(_CATCH_DISCOVER_TESTS_SCRIPT set(_CATCH_DISCOVER_TESTS_SCRIPT
${CMAKE_CURRENT_LIST_DIR}/CatchAddTests.cmake ${CMAKE_CURRENT_LIST_DIR}/CatchAddTests.cmake
CACHE INTERNAL "Catch2 full path to CatchAddTests.cmake helper file"
) )

View File

@@ -241,6 +241,7 @@ endfunction()
# entry point # entry point
function(ParseAndAddCatchTests TestTarget) function(ParseAndAddCatchTests TestTarget)
message(DEPRECATION "ParseAndAddCatchTest: function deprecated because of possibility of missed test cases. Consider using 'catch_discover_tests' from 'Catch.cmake'")
ParseAndAddCatchTests_PrintDebugMessage("Started parsing ${TestTarget}") ParseAndAddCatchTests_PrintDebugMessage("Started parsing ${TestTarget}")
get_target_property(SourceFiles ${TestTarget} SOURCES) get_target_property(SourceFiles ${TestTarget} SOURCES)
ParseAndAddCatchTests_PrintDebugMessage("Found the following sources: ${SourceFiles}") ParseAndAddCatchTests_PrintDebugMessage("Found the following sources: ${SourceFiles}")

View File

@@ -57,7 +57,7 @@ with automatically registering their `TEST_CASE`s with CTest. They
can be found in the `contrib` folder, and are can be found in the `contrib` folder, and are
1) `Catch.cmake` (and its dependency `CatchAddTests.cmake`) 1) `Catch.cmake` (and its dependency `CatchAddTests.cmake`)
2) `ParseAndAddCatchTests.cmake` 2) `ParseAndAddCatchTests.cmake` (deprecated)
If Catch2 has been installed in system, both of these can be used after If Catch2 has been installed in system, both of these can be used after
doing `find_package(Catch2 REQUIRED)`. Otherwise you need to add them doing `find_package(Catch2 REQUIRED)`. Otherwise you need to add them
@@ -176,10 +176,17 @@ the output file name e.g. ".xml".
### `ParseAndAddCatchTests.cmake` ### `ParseAndAddCatchTests.cmake`
⚠ This script is [deprecated](https://github.com/catchorg/Catch2/pull/2120)
in Catch 2.13.4 and superseded by the above approach using `catch_discover_tests`.
See [#2092](https://github.com/catchorg/Catch2/issues/2092) for details.
`ParseAndAddCatchTests` works by parsing all implementation files `ParseAndAddCatchTests` works by parsing all implementation files
associated with the provided target, and registering them via CTest's associated with the provided target, and registering them via CTest's
`add_test`. This approach has some limitations, such as the fact that `add_test`. This approach has some limitations, such as the fact that
commented-out tests will be registered anyway. commented-out tests will be registered anyway. More serious, only a
subset of the assertion macros currently available in Catch can be
detected by this script and tests with any macros that cannot be
parsed are *silently ignored*.
#### Usage #### Usage

View File

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

View File

@@ -2,6 +2,7 @@
# Release notes # Release notes
**Contents**<br> **Contents**<br>
[2.13.4](#2134)<br>
[2.13.3](#2133)<br> [2.13.3](#2133)<br>
[2.13.2](#2132)<br> [2.13.2](#2132)<br>
[2.13.1](#2131)<br> [2.13.1](#2131)<br>
@@ -44,6 +45,22 @@
[Even Older versions](#even-older-versions)<br> [Even Older versions](#even-older-versions)<br>
## 2.13.4
### Improvements
* Improved the hashing algorithm used for shuffling test cases (#2070)
* `TEST_CASE`s that differ only in the last character should be properly shuffled
* Note that this means that v2.13.4 gives you a different order of test cases than 2.13.3, even given the same seed.
### Miscellaneous
* Deprecated `ParseAndAddCatchTests` CMake integration (#2092)
* It is impossible to implement it properly for all the different test case variants Catch2 provides, and there are better options provided.
* Use `catch_discover_tests` instead, which uses runtime information about available tests.
* Fixed bug in `catch_discover_tests` that would cause it to fail when used in specific project structures (#2119)
* Added Bazel build file
* Added an experimental static library target to CMake
## 2.13.3 ## 2.13.3
### Fixes ### Fixes

View File

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

View File

@@ -11,7 +11,7 @@
#define CATCH_VERSION_MAJOR 2 #define CATCH_VERSION_MAJOR 2
#define CATCH_VERSION_MINOR 13 #define CATCH_VERSION_MINOR 13
#define CATCH_VERSION_PATCH 3 #define CATCH_VERSION_PATCH 4
#ifdef __clang__ #ifdef __clang__
# pragma clang system_header # pragma clang system_header

View File

@@ -22,24 +22,28 @@ namespace Catch {
namespace { namespace {
struct TestHasher { struct TestHasher {
explicit TestHasher(Catch::SimplePcg32& rng_instance) { using hash_t = uint64_t;
basis = rng_instance();
basis <<= 32;
basis |= rng_instance();
}
uint64_t basis; explicit TestHasher( hash_t hashSuffix ):
m_hashSuffix{ hashSuffix } {}
uint64_t operator()(TestCase const& t) const { uint32_t operator()( TestCase const& t ) const {
// Modified FNV-1a hash // FNV-1a hash with multiplication fold.
static constexpr uint64_t prime = 1099511628211; const hash_t prime = 1099511628211u;
uint64_t hash = basis; hash_t hash = 14695981039346656037u;
for (const char c : t.name) { for ( const char c : t.name ) {
hash ^= c; hash ^= c;
hash *= prime; hash *= prime;
} }
return hash; hash ^= m_hashSuffix;
hash *= prime;
const uint32_t low{ static_cast<uint32_t>( hash ) };
const uint32_t high{ static_cast<uint32_t>( hash >> 32 ) };
return low * high;
} }
private:
hash_t m_hashSuffix;
}; };
} // end unnamed namespace } // end unnamed namespace
@@ -58,9 +62,9 @@ namespace Catch {
case RunTests::InRandomOrder: { case RunTests::InRandomOrder: {
seedRng( config ); seedRng( config );
TestHasher h( rng() ); TestHasher h{ config.rngSeed() };
using hashedTest = std::pair<uint64_t, TestCase const*>; using hashedTest = std::pair<TestHasher::hash_t, TestCase const*>;
std::vector<hashedTest> indexed_tests; std::vector<hashedTest> indexed_tests;
indexed_tests.reserve( unsortedTestCases.size() ); indexed_tests.reserve( unsortedTestCases.size() );

View File

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

View File

@@ -129,8 +129,8 @@ def updateVersionDefine(version):
def updateVersionPlaceholder(filename, version): def updateVersionPlaceholder(filename, version):
with open(filename, 'rb') as file: with open(filename, 'rb') as file:
lines = file.readlines() lines = file.readlines()
placeholderRegex = re.compile(b' in Catch X.Y.Z') placeholderRegex = re.compile(b'in Catch X.Y.Z')
replacement = ' in Catch {}.{}.{}'.format(version.majorVersion, version.minorVersion, version.patchNumber).encode('ascii') replacement = 'in Catch {}.{}.{}'.format(version.majorVersion, version.minorVersion, version.patchNumber).encode('ascii')
with open(filename, 'wb') as file: with open(filename, 'wb') as file:
for line in lines: for line in lines:
file.write(placeholderRegex.sub(replacement, line)) file.write(placeholderRegex.sub(replacement, line))

View File

@@ -1,6 +1,6 @@
/* /*
* Catch v2.13.3 * Catch v2.13.4
* Generated: 2020-10-31 18:20:31.045274 * Generated: 2020-12-29 14:48:00.116107
* ---------------------------------------------------------- * ----------------------------------------------------------
* This file has been merged from multiple headers. Please don't edit it directly * This file has been merged from multiple headers. Please don't edit it directly
* Copyright (c) 2020 Two Blue Cubes Ltd. All rights reserved. * Copyright (c) 2020 Two Blue Cubes Ltd. All rights reserved.
@@ -15,7 +15,7 @@
#define CATCH_VERSION_MAJOR 2 #define CATCH_VERSION_MAJOR 2
#define CATCH_VERSION_MINOR 13 #define CATCH_VERSION_MINOR 13
#define CATCH_VERSION_PATCH 3 #define CATCH_VERSION_PATCH 4
#ifdef __clang__ #ifdef __clang__
# pragma clang system_header # pragma clang system_header
@@ -14126,24 +14126,28 @@ namespace Catch {
namespace { namespace {
struct TestHasher { struct TestHasher {
explicit TestHasher(Catch::SimplePcg32& rng_instance) { using hash_t = uint64_t;
basis = rng_instance();
basis <<= 32;
basis |= rng_instance();
}
uint64_t basis; explicit TestHasher( hash_t hashSuffix ):
m_hashSuffix{ hashSuffix } {}
uint64_t operator()(TestCase const& t) const { uint32_t operator()( TestCase const& t ) const {
// Modified FNV-1a hash // FNV-1a hash with multiplication fold.
static constexpr uint64_t prime = 1099511628211; const hash_t prime = 1099511628211u;
uint64_t hash = basis; hash_t hash = 14695981039346656037u;
for (const char c : t.name) { for ( const char c : t.name ) {
hash ^= c; hash ^= c;
hash *= prime; hash *= prime;
} }
return hash; hash ^= m_hashSuffix;
hash *= prime;
const uint32_t low{ static_cast<uint32_t>( hash ) };
const uint32_t high{ static_cast<uint32_t>( hash >> 32 ) };
return low * high;
} }
private:
hash_t m_hashSuffix;
}; };
} // end unnamed namespace } // end unnamed namespace
@@ -14161,9 +14165,9 @@ namespace Catch {
case RunTests::InRandomOrder: { case RunTests::InRandomOrder: {
seedRng( config ); seedRng( config );
TestHasher h( rng() ); TestHasher h{ config.rngSeed() };
using hashedTest = std::pair<uint64_t, TestCase const*>; using hashedTest = std::pair<TestHasher::hash_t, TestCase const*>;
std::vector<hashedTest> indexed_tests; std::vector<hashedTest> indexed_tests;
indexed_tests.reserve( unsortedTestCases.size() ); indexed_tests.reserve( unsortedTestCases.size() );
@@ -15316,7 +15320,7 @@ namespace Catch {
} }
Version const& libraryVersion() { Version const& libraryVersion() {
static Version version( 2, 13, 3, "", 0 ); static Version version( 2, 13, 4, "", 0 );
return version; return version;
} }

2
src/catch_with_main.cpp Normal file
View File

@@ -0,0 +1,2 @@
#define CATCH_CONFIG_MAIN
#include <catch2/catch.hpp>