mirror of
https://github.com/catchorg/Catch2.git
synced 2024-11-22 13:26:10 +01:00
Experimental static analysis support in TEST_CASE and SECTION
Closes #2681
This commit is contained in:
parent
dba9197ec7
commit
bf5aa7b383
@ -9,6 +9,7 @@
|
||||
#define CATCH_SECTION_HPP_INCLUDED
|
||||
|
||||
#include <catch2/internal/catch_compiler_capabilities.hpp>
|
||||
#include <catch2/internal/catch_config_static_analysis_support.hpp>
|
||||
#include <catch2/internal/catch_noncopyable.hpp>
|
||||
#include <catch2/catch_section_info.hpp>
|
||||
#include <catch2/catch_timer.hpp>
|
||||
@ -38,16 +39,62 @@ namespace Catch {
|
||||
|
||||
} // end namespace Catch
|
||||
|
||||
#if !defined(CATCH_CONFIG_EXPERIMENTAL_STATIC_ANALYSIS_SUPPORT)
|
||||
# define INTERNAL_CATCH_SECTION( ... ) \
|
||||
CATCH_INTERNAL_START_WARNINGS_SUPPRESSION \
|
||||
CATCH_INTERNAL_SUPPRESS_UNUSED_VARIABLE_WARNINGS \
|
||||
if( Catch::Section const& INTERNAL_CATCH_UNIQUE_NAME( catch_internal_Section ) = Catch::Section( CATCH_INTERNAL_LINEINFO, __VA_ARGS__ ) ) \
|
||||
if ( Catch::Section const& INTERNAL_CATCH_UNIQUE_NAME( \
|
||||
catch_internal_Section ) = \
|
||||
Catch::Section( CATCH_INTERNAL_LINEINFO, __VA_ARGS__ ) ) \
|
||||
CATCH_INTERNAL_STOP_WARNINGS_SUPPRESSION
|
||||
|
||||
# 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() ) ) \
|
||||
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
|
||||
|
||||
|
||||
#endif // CATCH_SECTION_HPP_INCLUDED
|
||||
|
@ -8,6 +8,7 @@
|
||||
#ifndef 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_noncopyable.hpp>
|
||||
#include <catch2/interfaces/catch_interfaces_test_invoker.hpp>
|
||||
@ -72,6 +73,9 @@ struct AutoReg : Detail::NonCopyable {
|
||||
void TestName::test()
|
||||
#endif
|
||||
|
||||
|
||||
#if !defined(CATCH_CONFIG_EXPERIMENTAL_STATIC_ANALYSIS_SUPPORT)
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
#define INTERNAL_CATCH_TESTCASE2( TestName, ... ) \
|
||||
static void TestName(); \
|
||||
@ -84,19 +88,40 @@ struct AutoReg : Detail::NonCopyable {
|
||||
#define INTERNAL_CATCH_TESTCASE( ... ) \
|
||||
INTERNAL_CATCH_TESTCASE2( INTERNAL_CATCH_UNIQUE_NAME( CATCH2_INTERNAL_TEST_ ), __VA_ARGS__ )
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
#define INTERNAL_CATCH_METHOD_AS_TEST_CASE( QualifiedMethod, ... ) \
|
||||
#else // ^^ !CATCH_CONFIG_EXPERIMENTAL_STATIC_ANALYSIS_SUPPORT | vv CATCH_CONFIG_EXPERIMENTAL_STATIC_ANALYSIS_SUPPORT
|
||||
|
||||
|
||||
// Dummy registrator for the dumy test case macros
|
||||
namespace Catch {
|
||||
namespace Detail {
|
||||
struct DummyUse {
|
||||
DummyUse( void ( * )( int ) );
|
||||
};
|
||||
} // namespace Detail
|
||||
} // namespace Catch
|
||||
|
||||
// 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 \
|
||||
namespace { \
|
||||
const Catch::AutoReg INTERNAL_CATCH_UNIQUE_NAME( autoRegistrar )( \
|
||||
Catch::makeTestInvoker( &QualifiedMethod ), \
|
||||
CATCH_INTERNAL_LINEINFO, \
|
||||
"&" #QualifiedMethod##_catch_sr, \
|
||||
Catch::NameAndTags{ __VA_ARGS__ } ); \
|
||||
} /* NOLINT */ \
|
||||
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, ... )\
|
||||
@ -118,6 +143,22 @@ struct AutoReg : Detail::NonCopyable {
|
||||
#define INTERNAL_CATCH_TEST_CASE_METHOD( ClassName, ... ) \
|
||||
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, ... ) \
|
||||
do { \
|
||||
|
Loading…
Reference in New Issue
Block a user