mirror of
https://github.com/catchorg/Catch2.git
synced 2024-11-26 07:16: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
|
#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
|
||||||
|
|
||||||
|
#if !defined(CATCH_CONFIG_EXPERIMENTAL_STATIC_ANALYSIS_SUPPORT)
|
||||||
# define INTERNAL_CATCH_SECTION( ... ) \
|
# define INTERNAL_CATCH_SECTION( ... ) \
|
||||||
CATCH_INTERNAL_START_WARNINGS_SUPPRESSION \
|
CATCH_INTERNAL_START_WARNINGS_SUPPRESSION \
|
||||||
CATCH_INTERNAL_SUPPRESS_UNUSED_VARIABLE_WARNINGS \
|
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
|
CATCH_INTERNAL_STOP_WARNINGS_SUPPRESSION
|
||||||
|
|
||||||
# define INTERNAL_CATCH_DYNAMIC_SECTION( ... ) \
|
# define INTERNAL_CATCH_DYNAMIC_SECTION( ... ) \
|
||||||
CATCH_INTERNAL_START_WARNINGS_SUPPRESSION \
|
CATCH_INTERNAL_START_WARNINGS_SUPPRESSION \
|
||||||
CATCH_INTERNAL_SUPPRESS_UNUSED_VARIABLE_WARNINGS \
|
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
|
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
|
#endif // CATCH_SECTION_HPP_INCLUDED
|
||||||
|
@ -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, ... ) \
|
|
||||||
|
|
||||||
|
// 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_START_WARNINGS_SUPPRESSION \
|
||||||
CATCH_INTERNAL_SUPPRESS_GLOBALS_WARNINGS \
|
CATCH_INTERNAL_SUPPRESS_GLOBALS_WARNINGS \
|
||||||
CATCH_INTERNAL_SUPPRESS_UNUSED_VARIABLE_WARNINGS \
|
CATCH_INTERNAL_SUPPRESS_UNUSED_VARIABLE_WARNINGS \
|
||||||
namespace { \
|
static const Catch::Detail::DummyUse INTERNAL_CATCH_UNIQUE_NAME( \
|
||||||
const Catch::AutoReg INTERNAL_CATCH_UNIQUE_NAME( autoRegistrar )( \
|
dummyUser )( &fname ); \
|
||||||
Catch::makeTestInvoker( &QualifiedMethod ), \
|
CATCH_INTERNAL_SUPPRESS_SHADOW_WARNINGS \
|
||||||
CATCH_INTERNAL_LINEINFO, \
|
static void fname( [[maybe_unused]] int catchInternalSectionHint ) \
|
||||||
"&" #QualifiedMethod##_catch_sr, \
|
|
||||||
Catch::NameAndTags{ __VA_ARGS__ } ); \
|
|
||||||
} /* NOLINT */ \
|
|
||||||
CATCH_INTERNAL_STOP_WARNINGS_SUPPRESSION
|
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 { \
|
||||||
|
Loading…
Reference in New Issue
Block a user