Merge branch 'devel' into devel

This commit is contained in:
ניר 2023-06-20 21:48:51 +03:00 committed by GitHub
commit d1de503150
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
44 changed files with 503 additions and 60 deletions

View File

@ -29,13 +29,13 @@ jobs:
build_type: Debug build_type: Debug
std: 14 std: 14
other_pkgs: g++-7 other_pkgs: g++-7
cmake_configurations: -DCATCH_BUILD_EXTRA_TESTS=ON -DCATCH_BUILD_EXAMPLES=ON cmake_configurations: -DCATCH_BUILD_EXTRA_TESTS=ON -DCATCH_BUILD_EXAMPLES=ON -DCATCH_ENABLE_CMAKE_HELPER_TESTS=ON
- cxx: g++-7 - cxx: g++-7
build_description: Extras + Examples build_description: Extras + Examples
build_type: Release build_type: Release
std: 14 std: 14
other_pkgs: g++-7 other_pkgs: g++-7
cmake_configurations: -DCATCH_BUILD_EXTRA_TESTS=ON -DCATCH_BUILD_EXAMPLES=ON cmake_configurations: -DCATCH_BUILD_EXTRA_TESTS=ON -DCATCH_BUILD_EXAMPLES=ON -DCATCH_ENABLE_CMAKE_HELPER_TESTS=ON
# Extras and examples with Clang-10 # Extras and examples with Clang-10
- cxx: clang++-10 - cxx: clang++-10
@ -43,13 +43,13 @@ jobs:
build_type: Debug build_type: Debug
std: 17 std: 17
other_pkgs: clang-10 other_pkgs: clang-10
cmake_configurations: -DCATCH_BUILD_EXTRA_TESTS=ON -DCATCH_BUILD_EXAMPLES=ON cmake_configurations: -DCATCH_BUILD_EXTRA_TESTS=ON -DCATCH_BUILD_EXAMPLES=ON -DCATCH_ENABLE_CMAKE_HELPER_TESTS=ON
- cxx: clang++-10 - cxx: clang++-10
build_description: Extras + Examples build_description: Extras + Examples
build_type: Release build_type: Release
std: 17 std: 17
other_pkgs: clang-10 other_pkgs: clang-10
cmake_configurations: -DCATCH_BUILD_EXTRA_TESTS=ON -DCATCH_BUILD_EXAMPLES=ON cmake_configurations: -DCATCH_BUILD_EXTRA_TESTS=ON -DCATCH_BUILD_EXAMPLES=ON -DCATCH_ENABLE_CMAKE_HELPER_TESTS=ON
# Configure tests with Clang-10 # Configure tests with Clang-10
- cxx: clang++-10 - cxx: clang++-10

View File

@ -43,12 +43,14 @@ expand_template(
"#cmakedefine CATCH_CONFIG_NO_GLOBAL_NEXTAFTER": "", "#cmakedefine CATCH_CONFIG_NO_GLOBAL_NEXTAFTER": "",
"#cmakedefine CATCH_CONFIG_NO_POSIX_SIGNALS": "", "#cmakedefine CATCH_CONFIG_NO_POSIX_SIGNALS": "",
"#cmakedefine CATCH_CONFIG_NO_USE_ASYNC": "", "#cmakedefine CATCH_CONFIG_NO_USE_ASYNC": "",
"#cmakedefine CATCH_CONFIG_NO_EXPERIMENTAL_STATIC_ANALYSIS_SUPPORT": "",
"#cmakedefine CATCH_CONFIG_NO_WCHAR": "", "#cmakedefine CATCH_CONFIG_NO_WCHAR": "",
"#cmakedefine CATCH_CONFIG_NO_WINDOWS_SEH": "", "#cmakedefine CATCH_CONFIG_NO_WINDOWS_SEH": "",
"#cmakedefine CATCH_CONFIG_NOSTDOUT": "", "#cmakedefine CATCH_CONFIG_NOSTDOUT": "",
"#cmakedefine CATCH_CONFIG_POSIX_SIGNALS": "", "#cmakedefine CATCH_CONFIG_POSIX_SIGNALS": "",
"#cmakedefine CATCH_CONFIG_PREFIX_ALL": "", "#cmakedefine CATCH_CONFIG_PREFIX_ALL": "",
"#cmakedefine CATCH_CONFIG_SHARED_LIBRARY": "", "#cmakedefine CATCH_CONFIG_SHARED_LIBRARY": "",
"#cmakedefine CATCH_CONFIG_EXPERIMENTAL_STATIC_ANALYSIS_SUPPORT": "",
"#cmakedefine CATCH_CONFIG_USE_ASYNC": "", "#cmakedefine CATCH_CONFIG_USE_ASYNC": "",
"#cmakedefine CATCH_CONFIG_WCHAR": "", "#cmakedefine CATCH_CONFIG_WCHAR": "",
"#cmakedefine CATCH_CONFIG_WINDOWS_CRTDBG": "", "#cmakedefine CATCH_CONFIG_WINDOWS_CRTDBG": "",

View File

@ -41,6 +41,7 @@ set(_OverridableOptions
"WCHAR" "WCHAR"
"WINDOWS_SEH" "WINDOWS_SEH"
"GETENV" "GETENV"
"EXPERIMENTAL_STATIC_ANALYSIS_SUPPORT"
) )
foreach(OptionName ${_OverridableOptions}) foreach(OptionName ${_OverridableOptions})

View File

@ -21,6 +21,7 @@ cmake_dependent_option(CATCH_ENABLE_COVERAGE "Generate coverage for codecov.io"
cmake_dependent_option(CATCH_ENABLE_WERROR "Enables Werror during build" ON "CATCH_DEVELOPMENT_BUILD" OFF) cmake_dependent_option(CATCH_ENABLE_WERROR "Enables Werror during build" ON "CATCH_DEVELOPMENT_BUILD" OFF)
cmake_dependent_option(CATCH_BUILD_SURROGATES "Enable generating and building surrogate TUs for the main headers" OFF "CATCH_DEVELOPMENT_BUILD" OFF) cmake_dependent_option(CATCH_BUILD_SURROGATES "Enable generating and building surrogate TUs for the main headers" OFF "CATCH_DEVELOPMENT_BUILD" OFF)
cmake_dependent_option(CATCH_ENABLE_CONFIGURE_TESTS "Enable CMake configuration tests. WARNING: VERY EXPENSIVE" OFF "CATCH_DEVELOPMENT_BUILD" OFF) cmake_dependent_option(CATCH_ENABLE_CONFIGURE_TESTS "Enable CMake configuration tests. WARNING: VERY EXPENSIVE" OFF "CATCH_DEVELOPMENT_BUILD" OFF)
cmake_dependent_option(CATCH_ENABLE_CMAKE_HELPER_TESTS "Enable CMake helper tests. WARNING: VERY EXPENSIVE" OFF "CATCH_DEVELOPMENT_BUILD" OFF)
# Catch2's build breaks if done in-tree. You probably should not build # Catch2's build breaks if done in-tree. You probably should not build

View File

@ -18,7 +18,8 @@
"CATCH_BUILD_EXAMPLES": "ON", "CATCH_BUILD_EXAMPLES": "ON",
"CATCH_BUILD_EXTRA_TESTS": "ON", "CATCH_BUILD_EXTRA_TESTS": "ON",
"CATCH_BUILD_SURROGATES": "ON", "CATCH_BUILD_SURROGATES": "ON",
"CATCH_ENABLE_CONFIGURE_TESTS": "ON" "CATCH_ENABLE_CONFIGURE_TESTS": "ON",
"CATCH_ENABLE_CMAKE_HELPER_TESTS": "ON"
} }
} }
] ]

View File

@ -4,10 +4,10 @@ load("@bazel_tools//tools/build_defs/repo:http.bzl", "http_archive")
http_archive( http_archive(
name = "bazel_skylib", name = "bazel_skylib",
sha256 = "b8a1527901774180afc798aeb28c4634bdccf19c4d98e7bdd1ce79d1fe9aaad7", sha256 = "66ffd9315665bfaafc96b52278f57c7e2dd09f5ede279ea6d39b2be471e7e3aa",
urls = [ urls = [
"https://mirror.bazel.build/github.com/bazelbuild/bazel-skylib/releases/download/1.4.1/bazel-skylib-1.4.1.tar.gz", "https://mirror.bazel.build/github.com/bazelbuild/bazel-skylib/releases/download/1.4.2/bazel-skylib-1.4.2.tar.gz",
"https://github.com/bazelbuild/bazel-skylib/releases/download/1.4.1/bazel-skylib-1.4.1.tar.gz", "https://github.com/bazelbuild/bazel-skylib/releases/download/1.4.2/bazel-skylib-1.4.2.tar.gz",
], ],
) )

View File

@ -15,6 +15,7 @@
[Enabling stringification](#enabling-stringification)<br> [Enabling stringification](#enabling-stringification)<br>
[Disabling exceptions](#disabling-exceptions)<br> [Disabling exceptions](#disabling-exceptions)<br>
[Overriding Catch's debug break (`-b`)](#overriding-catchs-debug-break--b)<br> [Overriding Catch's debug break (`-b`)](#overriding-catchs-debug-break--b)<br>
[Static analysis support](#static-analysis-support)<br>
Catch2 is designed to "just work" as much as possible, and most of the Catch2 is designed to "just work" as much as possible, and most of the
configuration options below are changed automatically during compilation, configuration options below are changed automatically during compilation,

View File

@ -221,3 +221,21 @@ For full example of implementing your own generator, look into Catch2's
examples, specifically examples, specifically
[Generators: Create your own generator](../examples/300-Gen-OwnGenerator.cpp). [Generators: Create your own generator](../examples/300-Gen-OwnGenerator.cpp).
### Handling empty generators
The generator interface assumes that a generator always has at least one
element. This is not always true, e.g. if the generator depends on an external
datafile, the file might be missing.
There are two ways to handle this, depending on whether you want this
to be an error or not.
* If empty generator **is** an error, throw an exception in constructor.
* If empty generator **is not** an error, use the [`SKIP`](skipping-passing-failing.md#skipping-test-cases-at-runtime) in constructor.
---
[Home](Readme.md#top)

View File

@ -52,7 +52,7 @@ its machine-readable XML output to file `result-junit.xml`, and the
uses ANSI colour codes for colouring the output. uses ANSI colour codes for colouring the output.
Using multiple reporters (or one reporter and one-or-more [event Using multiple reporters (or one reporter and one-or-more [event
listeners](event-listener.md#top)) can have surprisingly complex semantics listeners](event-listeners.md#top)) can have surprisingly complex semantics
when using customization points provided to reporters by Catch2, namely when using customization points provided to reporters by Catch2, namely
capturing stdout/stderr from test cases. capturing stdout/stderr from test cases.

View File

@ -84,6 +84,12 @@ 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) be overridden using the [--allow-running-no-tests](command-line.md#no-tests-override)
flag. flag.
### `SKIP` inside generators
You can also use the `SKIP` macro inside generator's constructor to handle
cases where the generator is empty, but you do not want to fail the test
case.
## Passing and failing test cases ## Passing and failing test cases

View File

@ -74,6 +74,10 @@ function(catch_discover_tests_impl)
) )
endif() endif()
# Make sure to escape ; (semicolons) in test names first, because
# that'd break the foreach loop for "Parse output" later and create
# wrongly splitted and thus failing test cases (false positives)
string(REPLACE ";" "\;" output "${output}")
string(REPLACE "\n" ";" output "${output}") string(REPLACE "\n" ";" output "${output}")
# Prepare reporter # Prepare reporter
@ -119,15 +123,16 @@ function(catch_discover_tests_impl)
# Parse output # Parse output
foreach(line ${output}) foreach(line ${output})
set(test ${line}) set(test "${line}")
# Escape characters in test case names that would be parsed by Catch2 # Escape characters in test case names that would be parsed by Catch2
set(test_name ${test}) # Note that the \ escaping must happen FIRST! Do not change the order.
foreach(char , [ ]) set(test_name "${test}")
string(REPLACE ${char} "\\${char}" test_name ${test_name}) foreach(char \\ , [ ])
string(REPLACE ${char} "\\${char}" test_name "${test_name}")
endforeach(char) endforeach(char)
# ...add output dir # ...add output dir
if(output_dir) if(output_dir)
string(REGEX REPLACE "[^A-Za-z0-9_]" "_" test_name_clean ${test_name}) string(REGEX REPLACE "[^A-Za-z0-9_]" "_" test_name_clean "${test_name}")
set(output_dir_arg "--out ${output_dir}/${output_prefix}${test_name_clean}${output_suffix}") set(output_dir_arg "--out ${output_dir}/${output_prefix}${test_name_clean}${output_suffix}")
endif() endif()

View File

@ -73,6 +73,7 @@ set(IMPL_HEADERS
${SOURCES_DIR}/internal/catch_compiler_capabilities.hpp ${SOURCES_DIR}/internal/catch_compiler_capabilities.hpp
${SOURCES_DIR}/internal/catch_config_android_logwrite.hpp ${SOURCES_DIR}/internal/catch_config_android_logwrite.hpp
${SOURCES_DIR}/internal/catch_config_counter.hpp ${SOURCES_DIR}/internal/catch_config_counter.hpp
${SOURCES_DIR}/internal/catch_config_static_analysis_support.hpp
${SOURCES_DIR}/internal/catch_config_uncaught_exceptions.hpp ${SOURCES_DIR}/internal/catch_config_uncaught_exceptions.hpp
${SOURCES_DIR}/internal/catch_config_wchar.hpp ${SOURCES_DIR}/internal/catch_config_wchar.hpp
${SOURCES_DIR}/internal/catch_console_colour.hpp ${SOURCES_DIR}/internal/catch_console_colour.hpp

View File

@ -54,6 +54,7 @@
#include <catch2/internal/catch_compiler_capabilities.hpp> #include <catch2/internal/catch_compiler_capabilities.hpp>
#include <catch2/internal/catch_config_android_logwrite.hpp> #include <catch2/internal/catch_config_android_logwrite.hpp>
#include <catch2/internal/catch_config_counter.hpp> #include <catch2/internal/catch_config_counter.hpp>
#include <catch2/internal/catch_config_static_analysis_support.hpp>
#include <catch2/internal/catch_config_uncaught_exceptions.hpp> #include <catch2/internal/catch_config_uncaught_exceptions.hpp>
#include <catch2/internal/catch_config_wchar.hpp> #include <catch2/internal/catch_config_wchar.hpp>
#include <catch2/internal/catch_console_colour.hpp> #include <catch2/internal/catch_console_colour.hpp>

View File

@ -169,6 +169,15 @@
#endif #endif
#cmakedefine CATCH_CONFIG_EXPERIMENTAL_STATIC_ANALYSIS_SUPPORT
#cmakedefine CATCH_CONFIG_NO_EXPERIMENTAL_STATIC_ANALYSIS_SUPPORT
#if defined( CATCH_CONFIG_EXPERIMENTAL_STATIC_ANALYSIS_SUPPORT ) && \
defined( CATCH_CONFIG_NO_EXPERIMENTAL_STATIC_ANALYSIS_SUPPORT )
# error Cannot force STATIC_ANALYSIS_SUPPORT to both ON and OFF
#endif
// ------ // ------
// Simple toggle defines // Simple toggle defines
// their value is never used and they cannot be overridden // their value is never used and they cannot be overridden

View File

@ -0,0 +1,34 @@
// 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
/** \file
* Wrapper for the STATIC_ANALYSIS_SUPPORT configuration option
*
* Some of Catch2's macros can be defined differently to work better with
* static analysis tools, like clang-tidy or coverity.
* Currently the main use case is to show that `SECTION`s are executed
* exclusively, and not all in one run of a `TEST_CASE`.
*/
#ifndef CATCH_CONFIG_STATIC_ANALYSIS_SUPPORT_HPP_INCLUDED
#define CATCH_CONFIG_STATIC_ANALYSIS_SUPPORT_HPP_INCLUDED
#include <catch2/catch_user_config.hpp>
#if defined(__clang_analyzer__) || defined(__COVERITY__)
#define CATCH_INTERNAL_CONFIG_STATIC_ANALYSIS_SUPPORT
#endif
#if defined( CATCH_INTERNAL_CONFIG_STATIC_ANALYSIS_SUPPORT ) && \
!defined( CATCH_CONFIG_NO_EXPERIMENTAL_STATIC_ANALYSIS_SUPPORT ) && \
!defined( CATCH_CONFIG_EXPERIMENTAL_STATIC_ANALYSIS_SUPPORT )
# define CATCH_CONFIG_EXPERIMENTAL_STATIC_ANALYSIS_SUPPORT
#endif
#endif // CATCH_CONFIG_STATIC_ANALYSIS_SUPPORT_HPP_INCLUDED

View File

@ -9,6 +9,7 @@
#define CATCH_SECTION_HPP_INCLUDED #define CATCH_SECTION_HPP_INCLUDED
#include <catch2/internal/catch_compiler_capabilities.hpp> #include <catch2/internal/catch_compiler_capabilities.hpp>
#include <catch2/internal/catch_config_static_analysis_support.hpp>
#include <catch2/internal/catch_noncopyable.hpp> #include <catch2/internal/catch_noncopyable.hpp>
#include <catch2/catch_section_info.hpp> #include <catch2/catch_section_info.hpp>
#include <catch2/catch_timer.hpp> #include <catch2/catch_timer.hpp>
@ -38,16 +39,62 @@ namespace Catch {
} // end namespace Catch } // end namespace Catch
#define INTERNAL_CATCH_SECTION( ... ) \ #if !defined(CATCH_CONFIG_EXPERIMENTAL_STATIC_ANALYSIS_SUPPORT)
CATCH_INTERNAL_START_WARNINGS_SUPPRESSION \ # define INTERNAL_CATCH_SECTION( ... ) \
CATCH_INTERNAL_SUPPRESS_UNUSED_VARIABLE_WARNINGS \ CATCH_INTERNAL_START_WARNINGS_SUPPRESSION \
if( Catch::Section const& INTERNAL_CATCH_UNIQUE_NAME( catch_internal_Section ) = Catch::Section( CATCH_INTERNAL_LINEINFO, __VA_ARGS__ ) ) \ CATCH_INTERNAL_SUPPRESS_UNUSED_VARIABLE_WARNINGS \
CATCH_INTERNAL_STOP_WARNINGS_SUPPRESSION if ( Catch::Section const& INTERNAL_CATCH_UNIQUE_NAME( \
catch_internal_Section ) = \
Catch::Section( CATCH_INTERNAL_LINEINFO, __VA_ARGS__ ) ) \
CATCH_INTERNAL_STOP_WARNINGS_SUPPRESSION
# define INTERNAL_CATCH_DYNAMIC_SECTION( ... ) \
CATCH_INTERNAL_START_WARNINGS_SUPPRESSION \
CATCH_INTERNAL_SUPPRESS_UNUSED_VARIABLE_WARNINGS \
if ( Catch::Section const& INTERNAL_CATCH_UNIQUE_NAME( \
catch_internal_Section ) = \
Catch::SectionInfo( \
CATCH_INTERNAL_LINEINFO, \
( Catch::ReusableStringStream() << __VA_ARGS__ ) \
.str() ) ) \
CATCH_INTERNAL_STOP_WARNINGS_SUPPRESSION
#else
// These section definitions imply that at most one section at one level
// will be intered (because only one section's __LINE__ can be equal to
// the dummy `catchInternalSectionHint` variable from `TEST_CASE`).
namespace Catch {
namespace Detail {
// Intentionally without linkage, as it should only be used as a dummy
// symbol for static analysis.
int GetNewSectionHint();
} // namespace Detail
} // namespace Catch
# define INTERNAL_CATCH_SECTION( ... ) \
CATCH_INTERNAL_START_WARNINGS_SUPPRESSION \
CATCH_INTERNAL_SUPPRESS_UNUSED_VARIABLE_WARNINGS \
CATCH_INTERNAL_SUPPRESS_SHADOW_WARNINGS \
if ( [[maybe_unused]] int catchInternalPreviousSectionHint = \
catchInternalSectionHint, \
catchInternalSectionHint = Catch::Detail::GetNewSectionHint(); \
catchInternalPreviousSectionHint == __LINE__ ) \
CATCH_INTERNAL_STOP_WARNINGS_SUPPRESSION
# define INTERNAL_CATCH_DYNAMIC_SECTION( ... ) \
CATCH_INTERNAL_START_WARNINGS_SUPPRESSION \
CATCH_INTERNAL_SUPPRESS_UNUSED_VARIABLE_WARNINGS \
CATCH_INTERNAL_SUPPRESS_SHADOW_WARNINGS \
if ( [[maybe_unused]] int catchInternalPreviousSectionHint = \
catchInternalSectionHint, \
catchInternalSectionHint = Catch::Detail::GetNewSectionHint(); \
catchInternalPreviousSectionHint == __LINE__ ) \
CATCH_INTERNAL_STOP_WARNINGS_SUPPRESSION
#endif
#define INTERNAL_CATCH_DYNAMIC_SECTION( ... ) \
CATCH_INTERNAL_START_WARNINGS_SUPPRESSION \
CATCH_INTERNAL_SUPPRESS_UNUSED_VARIABLE_WARNINGS \
if( Catch::Section const& INTERNAL_CATCH_UNIQUE_NAME( catch_internal_Section ) = Catch::SectionInfo( CATCH_INTERNAL_LINEINFO, (Catch::ReusableStringStream() << __VA_ARGS__).str() ) ) \
CATCH_INTERNAL_STOP_WARNINGS_SUPPRESSION
#endif // CATCH_SECTION_HPP_INCLUDED #endif // CATCH_SECTION_HPP_INCLUDED

View File

@ -8,6 +8,7 @@
#ifndef CATCH_TEST_REGISTRY_HPP_INCLUDED #ifndef CATCH_TEST_REGISTRY_HPP_INCLUDED
#define CATCH_TEST_REGISTRY_HPP_INCLUDED #define CATCH_TEST_REGISTRY_HPP_INCLUDED
#include <catch2/internal/catch_config_static_analysis_support.hpp>
#include <catch2/internal/catch_source_line_info.hpp> #include <catch2/internal/catch_source_line_info.hpp>
#include <catch2/internal/catch_noncopyable.hpp> #include <catch2/internal/catch_noncopyable.hpp>
#include <catch2/interfaces/catch_interfaces_test_invoker.hpp> #include <catch2/interfaces/catch_interfaces_test_invoker.hpp>
@ -72,6 +73,9 @@ struct AutoReg : Detail::NonCopyable {
void TestName::test() void TestName::test()
#endif #endif
#if !defined(CATCH_CONFIG_EXPERIMENTAL_STATIC_ANALYSIS_SUPPORT)
/////////////////////////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////////////////////////
#define INTERNAL_CATCH_TESTCASE2( TestName, ... ) \ #define INTERNAL_CATCH_TESTCASE2( TestName, ... ) \
static void TestName(); \ static void TestName(); \
@ -84,19 +88,40 @@ struct AutoReg : Detail::NonCopyable {
#define INTERNAL_CATCH_TESTCASE( ... ) \ #define INTERNAL_CATCH_TESTCASE( ... ) \
INTERNAL_CATCH_TESTCASE2( INTERNAL_CATCH_UNIQUE_NAME( CATCH2_INTERNAL_TEST_ ), __VA_ARGS__ ) INTERNAL_CATCH_TESTCASE2( INTERNAL_CATCH_UNIQUE_NAME( CATCH2_INTERNAL_TEST_ ), __VA_ARGS__ )
/////////////////////////////////////////////////////////////////////////////// #else // ^^ !CATCH_CONFIG_EXPERIMENTAL_STATIC_ANALYSIS_SUPPORT | vv CATCH_CONFIG_EXPERIMENTAL_STATIC_ANALYSIS_SUPPORT
#define INTERNAL_CATCH_METHOD_AS_TEST_CASE( QualifiedMethod, ... ) \
CATCH_INTERNAL_START_WARNINGS_SUPPRESSION \
CATCH_INTERNAL_SUPPRESS_GLOBALS_WARNINGS \ // Dummy registrator for the dumy test case macros
CATCH_INTERNAL_SUPPRESS_UNUSED_VARIABLE_WARNINGS \ namespace Catch {
namespace { \ namespace Detail {
const Catch::AutoReg INTERNAL_CATCH_UNIQUE_NAME( autoRegistrar )( \ struct DummyUse {
Catch::makeTestInvoker( &QualifiedMethod ), \ DummyUse( void ( * )( int ) );
CATCH_INTERNAL_LINEINFO, \ };
"&" #QualifiedMethod##_catch_sr, \ } // namespace Detail
Catch::NameAndTags{ __VA_ARGS__ } ); \ } // namespace Catch
} /* NOLINT */ \
CATCH_INTERNAL_STOP_WARNINGS_SUPPRESSION // Note that both the presence of the argument and its exact name are
// necessary for the section support.
// We provide a shadowed variable so that a `SECTION` inside non-`TEST_CASE`
// tests can compile. The redefined `TEST_CASE` shadows this with param.
static int catchInternalSectionHint = 0;
# define INTERNAL_CATCH_TESTCASE2( fname ) \
static void fname( int ); \
CATCH_INTERNAL_START_WARNINGS_SUPPRESSION \
CATCH_INTERNAL_SUPPRESS_GLOBALS_WARNINGS \
CATCH_INTERNAL_SUPPRESS_UNUSED_VARIABLE_WARNINGS \
static const Catch::Detail::DummyUse INTERNAL_CATCH_UNIQUE_NAME( \
dummyUser )( &fname ); \
CATCH_INTERNAL_SUPPRESS_SHADOW_WARNINGS \
static void fname( [[maybe_unused]] int catchInternalSectionHint ) \
CATCH_INTERNAL_STOP_WARNINGS_SUPPRESSION
# define INTERNAL_CATCH_TESTCASE( ... ) \
INTERNAL_CATCH_TESTCASE2( INTERNAL_CATCH_UNIQUE_NAME( dummyFunction ) )
#endif // CATCH_CONFIG_EXPERIMENTAL_STATIC_ANALYSIS_SUPPORT
/////////////////////////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////////////////////////
#define INTERNAL_CATCH_TEST_CASE_METHOD2( TestName, ClassName, ... )\ #define INTERNAL_CATCH_TEST_CASE_METHOD2( TestName, ClassName, ... )\
@ -118,6 +143,22 @@ struct AutoReg : Detail::NonCopyable {
#define INTERNAL_CATCH_TEST_CASE_METHOD( ClassName, ... ) \ #define INTERNAL_CATCH_TEST_CASE_METHOD( ClassName, ... ) \
INTERNAL_CATCH_TEST_CASE_METHOD2( INTERNAL_CATCH_UNIQUE_NAME( CATCH2_INTERNAL_TEST_ ), ClassName, __VA_ARGS__ ) INTERNAL_CATCH_TEST_CASE_METHOD2( INTERNAL_CATCH_UNIQUE_NAME( CATCH2_INTERNAL_TEST_ ), ClassName, __VA_ARGS__ )
///////////////////////////////////////////////////////////////////////////////
#define INTERNAL_CATCH_METHOD_AS_TEST_CASE( QualifiedMethod, ... ) \
CATCH_INTERNAL_START_WARNINGS_SUPPRESSION \
CATCH_INTERNAL_SUPPRESS_GLOBALS_WARNINGS \
CATCH_INTERNAL_SUPPRESS_UNUSED_VARIABLE_WARNINGS \
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
/////////////////////////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////////////////////////
#define INTERNAL_CATCH_REGISTER_TESTCASE( Function, ... ) \ #define INTERNAL_CATCH_REGISTER_TESTCASE( Function, ... ) \
do { \ do { \

View File

@ -78,6 +78,7 @@ internal_headers = [
'internal/catch_compiler_capabilities.hpp', 'internal/catch_compiler_capabilities.hpp',
'internal/catch_config_android_logwrite.hpp', 'internal/catch_config_android_logwrite.hpp',
'internal/catch_config_counter.hpp', 'internal/catch_config_counter.hpp',
'internal/catch_config_static_analysis_support.hpp',
'internal/catch_config_uncaught_exceptions.hpp', 'internal/catch_config_uncaught_exceptions.hpp',
'internal/catch_config_wchar.hpp', 'internal/catch_config_wchar.hpp',
'internal/catch_console_colour.hpp', 'internal/catch_console_colour.hpp',

View File

@ -622,6 +622,18 @@ if (CATCH_ENABLE_CONFIGURE_TESTS)
endforeach() endforeach()
endif() endif()
if (CATCH_ENABLE_CMAKE_HELPER_TESTS)
add_test(NAME "CMakeHelper::DiscoverTests"
COMMAND
"${PYTHON_EXECUTABLE}" "${CMAKE_CURRENT_LIST_DIR}/TestScripts/DiscoverTests/VerifyRegistration.py" "${CATCH_DIR}" "${CMAKE_CURRENT_BINARY_DIR}"
)
set_tests_properties("CMakeHelper::DiscoverTests"
PROPERTIES
COST 240
LABELS "uses-python"
)
endif()
foreach (reporterName # "Automake" - the simple .trs format does not support any kind of comments/metadata foreach (reporterName # "Automake" - the simple .trs format does not support any kind of comments/metadata
"compact" "compact"
"console" "console"

View File

@ -130,6 +130,7 @@ Nor would this
:test-result: FAIL Custom std-exceptions can be custom translated :test-result: FAIL Custom std-exceptions can be custom translated
:test-result: PASS Default scale is invisible to comparison :test-result: PASS Default scale is invisible to comparison
:test-result: PASS Directly creating an EnumInfo :test-result: PASS Directly creating an EnumInfo
:test-result: SKIP Empty generators can SKIP in constructor
:test-result: PASS Empty stream name opens cout stream :test-result: PASS Empty stream name opens cout stream
:test-result: FAIL EndsWith string matcher :test-result: FAIL EndsWith string matcher
:test-result: PASS Enums can quickly have stringification enabled using REGISTER_ENUM :test-result: PASS Enums can quickly have stringification enabled using REGISTER_ENUM

View File

@ -128,6 +128,7 @@
:test-result: FAIL Custom std-exceptions can be custom translated :test-result: FAIL Custom std-exceptions can be custom translated
:test-result: PASS Default scale is invisible to comparison :test-result: PASS Default scale is invisible to comparison
:test-result: PASS Directly creating an EnumInfo :test-result: PASS Directly creating an EnumInfo
:test-result: SKIP Empty generators can SKIP in constructor
:test-result: PASS Empty stream name opens cout stream :test-result: PASS Empty stream name opens cout stream
:test-result: FAIL EndsWith string matcher :test-result: FAIL EndsWith string matcher
:test-result: PASS Enums can quickly have stringification enabled using REGISTER_ENUM :test-result: PASS Enums can quickly have stringification enabled using REGISTER_ENUM

View File

@ -520,6 +520,7 @@ ToString.tests.cpp:<line number>: passed: enumInfo->lookup(1) == "Value2" for: V
ToString.tests.cpp:<line number>: passed: enumInfo->lookup(3) == "{** unexpected enum value **}" for: {** unexpected enum value **} ToString.tests.cpp:<line number>: passed: enumInfo->lookup(3) == "{** unexpected enum value **}" for: {** unexpected enum value **}
== ==
"{** unexpected enum value **}" "{** unexpected enum value **}"
Skip.tests.cpp:<line number>: skipped: 'This generator is empty'
Stream.tests.cpp:<line number>: passed: Catch::makeStream( "" )->isConsole() for: true Stream.tests.cpp:<line number>: passed: Catch::makeStream( "" )->isConsole() for: true
Matchers.tests.cpp:<line number>: failed: testStringForMatching(), EndsWith( "Substring" ) for: "this string contains 'abc' as a substring" ends with: "Substring" Matchers.tests.cpp:<line number>: failed: testStringForMatching(), EndsWith( "Substring" ) for: "this string contains 'abc' as a substring" ends with: "Substring"
Matchers.tests.cpp:<line number>: failed: testStringForMatching(), EndsWith( "this", Catch::CaseSensitive::No ) for: "this string contains 'abc' as a substring" ends with: "this" (case insensitive) Matchers.tests.cpp:<line number>: failed: testStringForMatching(), EndsWith( "this", Catch::CaseSensitive::No ) for: "this string contains 'abc' as a substring" ends with: "this" (case insensitive)
@ -2537,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: 408 | 308 passed | 84 failed | 5 skipped | 11 failed as expected test cases: 409 | 308 passed | 84 failed | 6 skipped | 11 failed as expected
assertions: 2225 | 2048 passed | 145 failed | 32 failed as expected assertions: 2225 | 2048 passed | 145 failed | 32 failed as expected

View File

@ -518,6 +518,7 @@ ToString.tests.cpp:<line number>: passed: enumInfo->lookup(1) == "Value2" for: V
ToString.tests.cpp:<line number>: passed: enumInfo->lookup(3) == "{** unexpected enum value **}" for: {** unexpected enum value **} ToString.tests.cpp:<line number>: passed: enumInfo->lookup(3) == "{** unexpected enum value **}" for: {** unexpected enum value **}
== ==
"{** unexpected enum value **}" "{** unexpected enum value **}"
Skip.tests.cpp:<line number>: skipped: 'This generator is empty'
Stream.tests.cpp:<line number>: passed: Catch::makeStream( "" )->isConsole() for: true Stream.tests.cpp:<line number>: passed: Catch::makeStream( "" )->isConsole() for: true
Matchers.tests.cpp:<line number>: failed: testStringForMatching(), EndsWith( "Substring" ) for: "this string contains 'abc' as a substring" ends with: "Substring" Matchers.tests.cpp:<line number>: failed: testStringForMatching(), EndsWith( "Substring" ) for: "this string contains 'abc' as a substring" ends with: "Substring"
Matchers.tests.cpp:<line number>: failed: testStringForMatching(), EndsWith( "this", Catch::CaseSensitive::No ) for: "this string contains 'abc' as a substring" ends with: "this" (case insensitive) Matchers.tests.cpp:<line number>: failed: testStringForMatching(), EndsWith( "this", Catch::CaseSensitive::No ) for: "this string contains 'abc' as a substring" ends with: "this" (case insensitive)
@ -2526,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: 408 | 308 passed | 84 failed | 5 skipped | 11 failed as expected test cases: 409 | 308 passed | 84 failed | 6 skipped | 11 failed as expected
assertions: 2225 | 2048 passed | 145 failed | 32 failed as expected assertions: 2225 | 2048 passed | 145 failed | 32 failed as expected

View File

@ -383,6 +383,16 @@ Exception.tests.cpp:<line number>: FAILED:
due to unexpected exception with message: due to unexpected exception with message:
custom std exception custom std exception
-------------------------------------------------------------------------------
Empty generators can SKIP in constructor
-------------------------------------------------------------------------------
Skip.tests.cpp:<line number>
...............................................................................
Skip.tests.cpp:<line number>: SKIPPED:
explicitly with message:
This generator is empty
------------------------------------------------------------------------------- -------------------------------------------------------------------------------
EndsWith string matcher EndsWith string matcher
------------------------------------------------------------------------------- -------------------------------------------------------------------------------
@ -1533,6 +1543,6 @@ due to unexpected exception with message:
Why would you throw a std::string? Why would you throw a std::string?
=============================================================================== ===============================================================================
test cases: 408 | 322 passed | 69 failed | 6 skipped | 11 failed as expected test cases: 409 | 322 passed | 69 failed | 7 skipped | 11 failed as expected
assertions: 2208 | 2048 passed | 128 failed | 32 failed as expected assertions: 2208 | 2048 passed | 128 failed | 32 failed as expected

View File

@ -3956,6 +3956,16 @@ with expansion:
== ==
"{** unexpected enum value **}" "{** unexpected enum value **}"
-------------------------------------------------------------------------------
Empty generators can SKIP in constructor
-------------------------------------------------------------------------------
Skip.tests.cpp:<line number>
...............................................................................
Skip.tests.cpp:<line number>: SKIPPED:
explicitly with message:
This generator is empty
------------------------------------------------------------------------------- -------------------------------------------------------------------------------
Empty stream name opens cout stream Empty stream name opens cout stream
------------------------------------------------------------------------------- -------------------------------------------------------------------------------
@ -18222,6 +18232,6 @@ Misc.tests.cpp:<line number>
Misc.tests.cpp:<line number>: PASSED: Misc.tests.cpp:<line number>: PASSED:
=============================================================================== ===============================================================================
test cases: 408 | 308 passed | 84 failed | 5 skipped | 11 failed as expected test cases: 409 | 308 passed | 84 failed | 6 skipped | 11 failed as expected
assertions: 2225 | 2048 passed | 145 failed | 32 failed as expected assertions: 2225 | 2048 passed | 145 failed | 32 failed as expected

View File

@ -3954,6 +3954,16 @@ with expansion:
== ==
"{** unexpected enum value **}" "{** unexpected enum value **}"
-------------------------------------------------------------------------------
Empty generators can SKIP in constructor
-------------------------------------------------------------------------------
Skip.tests.cpp:<line number>
...............................................................................
Skip.tests.cpp:<line number>: SKIPPED:
explicitly with message:
This generator is empty
------------------------------------------------------------------------------- -------------------------------------------------------------------------------
Empty stream name opens cout stream Empty stream name opens cout stream
------------------------------------------------------------------------------- -------------------------------------------------------------------------------
@ -18211,6 +18221,6 @@ Misc.tests.cpp:<line number>
Misc.tests.cpp:<line number>: PASSED: Misc.tests.cpp:<line number>: PASSED:
=============================================================================== ===============================================================================
test cases: 408 | 308 passed | 84 failed | 5 skipped | 11 failed as expected test cases: 409 | 308 passed | 84 failed | 6 skipped | 11 failed as expected
assertions: 2225 | 2048 passed | 145 failed | 32 failed as expected assertions: 2225 | 2048 passed | 145 failed | 32 failed as expected

View File

@ -1,7 +1,7 @@
<?xml version="1.0" encoding="UTF-8"?> <?xml version="1.0" encoding="UTF-8"?>
<testsuitesloose text artifact <testsuitesloose text artifact
> >
<testsuite name="<exe-name>" errors="17" failures="128" skipped="11" tests="2236" hostname="tbd" time="{duration}" timestamp="{iso8601-timestamp}"> <testsuite name="<exe-name>" errors="17" failures="128" skipped="12" tests="2237" hostname="tbd" time="{duration}" timestamp="{iso8601-timestamp}">
<properties> <properties>
<property name="random-seed" value="1"/> <property name="random-seed" value="1"/>
<property name="filters" value="&quot;*&quot; ~[!nonportable] ~[!benchmark] ~[approvals]"/> <property name="filters" value="&quot;*&quot; ~[!nonportable] ~[!benchmark] ~[approvals]"/>
@ -462,6 +462,13 @@ at Exception.tests.cpp:<line number>
</testcase> </testcase>
<testcase classname="<exe-name>.global" name="Default scale is invisible to comparison" time="{duration}" status="run"/> <testcase classname="<exe-name>.global" name="Default scale is invisible to comparison" time="{duration}" status="run"/>
<testcase classname="<exe-name>.global" name="Directly creating an EnumInfo" time="{duration}" status="run"/> <testcase classname="<exe-name>.global" name="Directly creating an EnumInfo" time="{duration}" status="run"/>
<testcase classname="<exe-name>.global" name="Empty generators can SKIP in constructor" time="{duration}" status="run">
<skipped type="SKIP">
SKIPPED
This generator is empty
at Skip.tests.cpp:<line number>
</skipped>
</testcase>
<testcase classname="<exe-name>.global" name="Empty stream name opens cout stream" time="{duration}" status="run"/> <testcase classname="<exe-name>.global" name="Empty stream name opens cout stream" time="{duration}" status="run"/>
<testcase classname="<exe-name>.global" name="EndsWith string matcher" time="{duration}" status="run"> <testcase classname="<exe-name>.global" name="EndsWith string matcher" time="{duration}" status="run">
<failure message="testStringForMatching(), EndsWith( &quot;Substring&quot; )" type="CHECK_THAT"> <failure message="testStringForMatching(), EndsWith( &quot;Substring&quot; )" type="CHECK_THAT">

View File

@ -1,6 +1,6 @@
<?xml version="1.0" encoding="UTF-8"?> <?xml version="1.0" encoding="UTF-8"?>
<testsuites> <testsuites>
<testsuite name="<exe-name>" errors="17" failures="128" skipped="11" tests="2236" hostname="tbd" time="{duration}" timestamp="{iso8601-timestamp}"> <testsuite name="<exe-name>" errors="17" failures="128" skipped="12" tests="2237" hostname="tbd" time="{duration}" timestamp="{iso8601-timestamp}">
<properties> <properties>
<property name="random-seed" value="1"/> <property name="random-seed" value="1"/>
<property name="filters" value="&quot;*&quot; ~[!nonportable] ~[!benchmark] ~[approvals]"/> <property name="filters" value="&quot;*&quot; ~[!nonportable] ~[!benchmark] ~[approvals]"/>
@ -461,6 +461,13 @@ at Exception.tests.cpp:<line number>
</testcase> </testcase>
<testcase classname="<exe-name>.global" name="Default scale is invisible to comparison" time="{duration}" status="run"/> <testcase classname="<exe-name>.global" name="Default scale is invisible to comparison" time="{duration}" status="run"/>
<testcase classname="<exe-name>.global" name="Directly creating an EnumInfo" time="{duration}" status="run"/> <testcase classname="<exe-name>.global" name="Directly creating an EnumInfo" time="{duration}" status="run"/>
<testcase classname="<exe-name>.global" name="Empty generators can SKIP in constructor" time="{duration}" status="run">
<skipped type="SKIP">
SKIPPED
This generator is empty
at Skip.tests.cpp:<line number>
</skipped>
</testcase>
<testcase classname="<exe-name>.global" name="Empty stream name opens cout stream" time="{duration}" status="run"/> <testcase classname="<exe-name>.global" name="Empty stream name opens cout stream" time="{duration}" status="run"/>
<testcase classname="<exe-name>.global" name="EndsWith string matcher" time="{duration}" status="run"> <testcase classname="<exe-name>.global" name="EndsWith string matcher" time="{duration}" status="run">
<failure message="testStringForMatching(), EndsWith( &quot;Substring&quot; )" type="CHECK_THAT"> <failure message="testStringForMatching(), EndsWith( &quot;Substring&quot; )" type="CHECK_THAT">

View File

@ -1870,6 +1870,13 @@ at Misc.tests.cpp:<line number>
<testCase name="xmlentitycheck/encoded chars: these should all be encoded: &amp;&amp;&amp;&quot;&quot;&quot;&lt;&lt;&lt;&amp;&quot;&lt;&lt;&amp;&quot;" duration="{duration}"/> <testCase name="xmlentitycheck/encoded chars: these should all be encoded: &amp;&amp;&amp;&quot;&quot;&quot;&lt;&lt;&lt;&amp;&quot;&lt;&lt;&amp;&quot;" duration="{duration}"/>
</file> </file>
<file path="tests/<exe-name>/UsageTests/Skip.tests.cpp"> <file path="tests/<exe-name>/UsageTests/Skip.tests.cpp">
<testCase name="Empty generators can SKIP in constructor" duration="{duration}">
<skipped message="SKIP()">
SKIPPED
This generator is empty
at Skip.tests.cpp:<line number>
</skipped>
</testCase>
<testCase name="a succeeding test can still be skipped" duration="{duration}"> <testCase name="a succeeding test can still be skipped" duration="{duration}">
<skipped message="SKIP()"> <skipped message="SKIP()">
SKIPPED SKIPPED

View File

@ -1869,6 +1869,13 @@ at Misc.tests.cpp:<line number>
<testCase name="xmlentitycheck/encoded chars: these should all be encoded: &amp;&amp;&amp;&quot;&quot;&quot;&lt;&lt;&lt;&amp;&quot;&lt;&lt;&amp;&quot;" duration="{duration}"/> <testCase name="xmlentitycheck/encoded chars: these should all be encoded: &amp;&amp;&amp;&quot;&quot;&quot;&lt;&lt;&lt;&amp;&quot;&lt;&lt;&amp;&quot;" duration="{duration}"/>
</file> </file>
<file path="tests/<exe-name>/UsageTests/Skip.tests.cpp"> <file path="tests/<exe-name>/UsageTests/Skip.tests.cpp">
<testCase name="Empty generators can SKIP in constructor" duration="{duration}">
<skipped message="SKIP()">
SKIPPED
This generator is empty
at Skip.tests.cpp:<line number>
</skipped>
</testCase>
<testCase name="a succeeding test can still be skipped" duration="{duration}"> <testCase name="a succeeding test can still be skipped" duration="{duration}">
<skipped message="SKIP()"> <skipped message="SKIP()">
SKIPPED SKIPPED

View File

@ -984,6 +984,8 @@ ok {test-number} - enumInfo->lookup(0) == "Value1" for: Value1 == "Value1"
ok {test-number} - enumInfo->lookup(1) == "Value2" for: Value2 == "Value2" ok {test-number} - enumInfo->lookup(1) == "Value2" for: Value2 == "Value2"
# Directly creating an EnumInfo # Directly creating an EnumInfo
ok {test-number} - enumInfo->lookup(3) == "{** unexpected enum value **}" for: {** unexpected enum value **} == "{** unexpected enum value **}" ok {test-number} - enumInfo->lookup(3) == "{** unexpected enum value **}" for: {** unexpected enum value **} == "{** unexpected enum value **}"
# Empty generators can SKIP in constructor
ok {test-number} - # SKIP 'This generator is empty'
# Empty stream name opens cout stream # Empty stream name opens cout stream
ok {test-number} - Catch::makeStream( "" )->isConsole() for: true ok {test-number} - Catch::makeStream( "" )->isConsole() for: true
# EndsWith string matcher # EndsWith string matcher
@ -4475,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..2236 1..2237

View File

@ -982,6 +982,8 @@ ok {test-number} - enumInfo->lookup(0) == "Value1" for: Value1 == "Value1"
ok {test-number} - enumInfo->lookup(1) == "Value2" for: Value2 == "Value2" ok {test-number} - enumInfo->lookup(1) == "Value2" for: Value2 == "Value2"
# Directly creating an EnumInfo # Directly creating an EnumInfo
ok {test-number} - enumInfo->lookup(3) == "{** unexpected enum value **}" for: {** unexpected enum value **} == "{** unexpected enum value **}" ok {test-number} - enumInfo->lookup(3) == "{** unexpected enum value **}" for: {** unexpected enum value **} == "{** unexpected enum value **}"
# Empty generators can SKIP in constructor
ok {test-number} - # SKIP 'This generator is empty'
# Empty stream name opens cout stream # Empty stream name opens cout stream
ok {test-number} - Catch::makeStream( "" )->isConsole() for: true ok {test-number} - Catch::makeStream( "" )->isConsole() for: true
# EndsWith string matcher # EndsWith string matcher
@ -4464,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..2236 1..2237

View File

@ -299,6 +299,9 @@
##teamcity[testFinished name='Default scale is invisible to comparison' duration="{duration}"] ##teamcity[testFinished name='Default scale is invisible to comparison' duration="{duration}"]
##teamcity[testStarted name='Directly creating an EnumInfo'] ##teamcity[testStarted name='Directly creating an EnumInfo']
##teamcity[testFinished name='Directly creating an EnumInfo' duration="{duration}"] ##teamcity[testFinished name='Directly creating an EnumInfo' duration="{duration}"]
##teamcity[testStarted name='Empty generators can SKIP in constructor']
##teamcity[testIgnored name='Empty generators can SKIP in constructor' message='Skip.tests.cpp:<line number>|n...............................................................................|n|nSkip.tests.cpp:<line number>|nexplicit skip with message:|n "This generator is empty"']
##teamcity[testFinished name='Empty generators can SKIP in constructor' duration="{duration}"]
##teamcity[testStarted name='Empty stream name opens cout stream'] ##teamcity[testStarted name='Empty stream name opens cout stream']
##teamcity[testFinished name='Empty stream name opens cout stream' duration="{duration}"] ##teamcity[testFinished name='Empty stream name opens cout stream' duration="{duration}"]
##teamcity[testStarted name='EndsWith string matcher'] ##teamcity[testStarted name='EndsWith string matcher']

View File

@ -299,6 +299,9 @@
##teamcity[testFinished name='Default scale is invisible to comparison' duration="{duration}"] ##teamcity[testFinished name='Default scale is invisible to comparison' duration="{duration}"]
##teamcity[testStarted name='Directly creating an EnumInfo'] ##teamcity[testStarted name='Directly creating an EnumInfo']
##teamcity[testFinished name='Directly creating an EnumInfo' duration="{duration}"] ##teamcity[testFinished name='Directly creating an EnumInfo' duration="{duration}"]
##teamcity[testStarted name='Empty generators can SKIP in constructor']
##teamcity[testIgnored name='Empty generators can SKIP in constructor' message='Skip.tests.cpp:<line number>|n...............................................................................|n|nSkip.tests.cpp:<line number>|nexplicit skip with message:|n "This generator is empty"']
##teamcity[testFinished name='Empty generators can SKIP in constructor' duration="{duration}"]
##teamcity[testStarted name='Empty stream name opens cout stream'] ##teamcity[testStarted name='Empty stream name opens cout stream']
##teamcity[testFinished name='Empty stream name opens cout stream' duration="{duration}"] ##teamcity[testFinished name='Empty stream name opens cout stream' duration="{duration}"]
##teamcity[testStarted name='EndsWith string matcher'] ##teamcity[testStarted name='EndsWith string matcher']

View File

@ -4364,6 +4364,12 @@ C
</Expression> </Expression>
<OverallResult success="true" skips="0"/> <OverallResult success="true" skips="0"/>
</TestCase> </TestCase>
<TestCase name="Empty generators can SKIP in constructor" tags="[skipping]" filename="tests/<exe-name>/UsageTests/Skip.tests.cpp" >
<Skip filename="tests/<exe-name>/UsageTests/Skip.tests.cpp" >
This generator is empty
</Skip>
<OverallResult success="true" skips="1"/>
</TestCase>
<TestCase name="Empty stream name opens cout stream" tags="[streams]" filename="tests/<exe-name>/IntrospectiveTests/Stream.tests.cpp" > <TestCase name="Empty stream name opens cout stream" tags="[streams]" filename="tests/<exe-name>/IntrospectiveTests/Stream.tests.cpp" >
<Expression success="true" type="REQUIRE" filename="tests/<exe-name>/IntrospectiveTests/Stream.tests.cpp" > <Expression success="true" type="REQUIRE" filename="tests/<exe-name>/IntrospectiveTests/Stream.tests.cpp" >
<Original> <Original>
@ -21192,6 +21198,6 @@ b1!
</Section> </Section>
<OverallResult success="true" skips="0"/> <OverallResult success="true" skips="0"/>
</TestCase> </TestCase>
<OverallResults successes="2048" failures="145" expectedFailures="32" skips="11"/> <OverallResults successes="2048" failures="145" expectedFailures="32" skips="12"/>
<OverallResultsCases successes="308" failures="84" expectedFailures="11" skips="5"/> <OverallResultsCases successes="308" failures="84" expectedFailures="11" skips="6"/>
</Catch2TestRun> </Catch2TestRun>

View File

@ -4364,6 +4364,12 @@ C
</Expression> </Expression>
<OverallResult success="true" skips="0"/> <OverallResult success="true" skips="0"/>
</TestCase> </TestCase>
<TestCase name="Empty generators can SKIP in constructor" tags="[skipping]" filename="tests/<exe-name>/UsageTests/Skip.tests.cpp" >
<Skip filename="tests/<exe-name>/UsageTests/Skip.tests.cpp" >
This generator is empty
</Skip>
<OverallResult success="true" skips="1"/>
</TestCase>
<TestCase name="Empty stream name opens cout stream" tags="[streams]" filename="tests/<exe-name>/IntrospectiveTests/Stream.tests.cpp" > <TestCase name="Empty stream name opens cout stream" tags="[streams]" filename="tests/<exe-name>/IntrospectiveTests/Stream.tests.cpp" >
<Expression success="true" type="REQUIRE" filename="tests/<exe-name>/IntrospectiveTests/Stream.tests.cpp" > <Expression success="true" type="REQUIRE" filename="tests/<exe-name>/IntrospectiveTests/Stream.tests.cpp" >
<Original> <Original>
@ -21191,6 +21197,6 @@ b1!
</Section> </Section>
<OverallResult success="true" skips="0"/> <OverallResult success="true" skips="0"/>
</TestCase> </TestCase>
<OverallResults successes="2048" failures="145" expectedFailures="32" skips="11"/> <OverallResults successes="2048" failures="145" expectedFailures="32" skips="12"/>
<OverallResultsCases successes="308" failures="84" expectedFailures="11" skips="5"/> <OverallResultsCases successes="308" failures="84" expectedFailures="11" skips="6"/>
</Catch2TestRun> </Catch2TestRun>

View File

@ -95,8 +95,8 @@ namespace {
MoveChecker() = default; MoveChecker() = default;
MoveChecker( MoveChecker const& rhs ) = default; MoveChecker( MoveChecker const& rhs ) = default;
MoveChecker& operator=( MoveChecker const& rhs ) = default; MoveChecker& operator=( MoveChecker const& rhs ) = default;
MoveChecker( MoveChecker&& rhs ) { rhs.has_moved = true; } MoveChecker( MoveChecker&& rhs ) noexcept { rhs.has_moved = true; }
MoveChecker& operator=( MoveChecker&& rhs ) { MoveChecker& operator=( MoveChecker&& rhs ) noexcept {
rhs.has_moved = true; rhs.has_moved = true;
return *this; return *this;
} }

View File

@ -163,7 +163,7 @@ namespace {
std::vector<std::string>& recorder, std::vector<std::string>& recorder,
Catch::IConfig const* config ): Catch::IConfig const* config ):
EventListenerBase( config ), EventListenerBase( config ),
m_witness( witness ), m_witness( CATCH_MOVE(witness) ),
m_recorder( recorder ) m_recorder( recorder )
{} {}
@ -181,7 +181,7 @@ namespace {
std::vector<std::string>& recorder, std::vector<std::string>& recorder,
Catch::ReporterConfig&& config ): Catch::ReporterConfig&& config ):
StreamingReporterBase( CATCH_MOVE(config) ), StreamingReporterBase( CATCH_MOVE(config) ),
m_witness( witness ), m_witness( CATCH_MOVE(witness) ),
m_recorder( recorder ) m_recorder( recorder )
{} {}

View File

@ -261,6 +261,10 @@ TEST_CASE("Copy and then generate a range", "[generators]") {
} }
} }
#if defined( __clang__ )
# pragma clang diagnostic pop
#endif
TEST_CASE("#1913 - GENERATE inside a for loop should not keep recreating the generator", "[regression][generators]") { TEST_CASE("#1913 - GENERATE inside a for loop should not keep recreating the generator", "[regression][generators]") {
static int counter = 0; static int counter = 0;
for (int i = 0; i < 3; ++i) { for (int i = 0; i < 3; ++i) {
@ -305,9 +309,5 @@ TEST_CASE( "#2615 - Throwing in constructor generator fails test case but does n
// this should fail the test case, but not abort the application // this should fail the test case, but not abort the application
auto sample = GENERATE( make_test_generator() ); auto sample = GENERATE( make_test_generator() );
// this assertion shouldn't trigger // this assertion shouldn't trigger
REQUIRE( sample == 0U ); REQUIRE( sample == 0 );
} }
#if defined( __clang__ )
# pragma clang diagnostic pop
#endif

View File

@ -890,7 +890,7 @@ struct MatcherA : Catch::Matchers::MatcherGenericBase {
return "equals: (int) 1 or (string) \"1\""; return "equals: (int) 1 or (string) \"1\"";
} }
bool match( int i ) const { return i == 1; } bool match( int i ) const { return i == 1; }
bool match( std::string s ) const { return s == "1"; } bool match( std::string const& s ) const { return s == "1"; }
}; };
struct MatcherB : Catch::Matchers::MatcherGenericBase { struct MatcherB : Catch::Matchers::MatcherGenericBase {

View File

@ -71,3 +71,30 @@ TEST_CASE( "failing for some generator values causes entire test case to fail",
FAIL(); FAIL();
} }
} }
namespace {
class test_skip_generator : public Catch::Generators::IGenerator<int> {
public:
explicit test_skip_generator() { SKIP( "This generator is empty" ); }
auto get() const -> int const& override {
static constexpr int value = 1;
return value;
}
auto next() -> bool override { return false; }
};
static auto make_test_skip_generator()
-> Catch::Generators::GeneratorWrapper<int> {
return { new test_skip_generator() };
}
} // namespace
TEST_CASE( "Empty generators can SKIP in constructor", "[skipping]" ) {
// The generator signals emptiness with `SKIP`
auto sample = GENERATE( make_test_skip_generator() );
// This assertion would fail, but shouldn't trigger
REQUIRE( sample == 0 );
}

View File

@ -0,0 +1,16 @@
cmake_minimum_required(VERSION 3.10)
project(discover-tests-test
LANGUAGES CXX
)
add_executable(tests
register-tests.cpp
)
add_subdirectory(${CATCH2_PATH} catch2-build)
target_link_libraries(tests PRIVATE Catch2::Catch2WithMain)
include(CTest)
include(Catch)
catch_discover_tests(tests)

View File

@ -0,0 +1,123 @@
#!/usr/bin/env python3
# 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
import os
import subprocess
import sys
def build_project(sources_dir, output_base_path, catch2_path):
build_dir = os.path.join(output_base_path, 'ctest-registration-test')
config_cmd = ['cmake',
'-B', build_dir,
'-S', sources_dir,
f'-DCATCH2_PATH={catch2_path}',
'-DCMAKE_BUILD_TYPE=Debug']
build_cmd = ['cmake',
'--build', build_dir,
'--config', 'Debug']
try:
subprocess.run(config_cmd,
capture_output = True,
check = True,
text = True)
subprocess.run(build_cmd,
capture_output = True,
check = True,
text = True)
except subprocess.CalledProcessError as err:
print('Error when building the test project')
print(f'cmd: {err.cmd}')
print(f'stderr: {err.stderr}')
print(f'stdout: {err.stdout}')
exit(3)
return build_dir
def get_test_names(build_path):
# For now we assume that Windows builds are done using MSBuild under
# Debug configuration. This means that we need to add "Debug" folder
# to the path when constructing it. On Linux, we don't add anything.
config_path = "Debug" if os.name == 'nt' else ""
full_path = os.path.join(build_path, config_path, 'tests')
cmd = [full_path, '--reporter', 'xml', '--list-tests']
result = subprocess.run(cmd,
capture_output = True,
check = True,
text = True)
import xml.etree.ElementTree as ET
root = ET.fromstring(result.stdout)
return [tc.text for tc in root.findall('TestCase/Name')]
def list_ctest_tests(build_path):
old_path = os.getcwd()
os.chdir(build_path)
cmd = ['ctest', '-C', 'debug', '--show-only=json-v1']
result = subprocess.run(cmd,
capture_output = True,
check = True,
text = True)
os.chdir(old_path)
import json
ctest_response = json.loads(result.stdout)
tests = ctest_response['tests']
test_names = []
for test in tests:
test_command = test['command']
# First part of the command is the binary, second is the filter.
# If there are less, registration has failed. If there are more,
# registration has changed and the script needs updating.
assert len(test_command) == 2
test_names.append(test_command[1])
test_name = test_command[1]
return test_names
def escape_catch2_test_name(name):
for char in ('\\', ',', '[', ']'):
name = name.replace(char, f"\\{char}")
return name
if __name__ == '__main__':
if len(sys.argv) != 3:
print(f'Usage: {sys.argv[0]} path-to-catch2-cml output-path')
exit(2)
catch2_path = sys.argv[1]
output_base_path = sys.argv[2]
sources_dir = os.path.dirname(os.path.abspath(sys.argv[0]))
build_path = build_project(sources_dir, output_base_path, catch2_path)
catch_test_names = [escape_catch2_test_name(name) for name in get_test_names(build_path)]
ctest_test_names = list_ctest_tests(build_path)
mismatched = 0
for catch_test in catch_test_names:
if catch_test not in ctest_test_names:
print(f"Catch2 test '{catch_test}' not found in CTest")
mismatched += 1
for ctest_test in ctest_test_names:
if ctest_test not in catch_test_names:
print(f"CTest test '{ctest_test}' not found in Catch2")
mismatched += 1
if mismatched:
print(f"Found {mismatched} mismatched tests catch test names and ctest test commands!")
exit(1)

View File

@ -0,0 +1,12 @@
// 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("@Script[C:\\EPM1A]=x;\"SCALA_ZERO:\"", "[script regressions]"){}
TEST_CASE("Some test") {}