Properly handle startup reporter registration errors

This commit is contained in:
Martin Hořeňovský 2022-05-15 10:35:07 +02:00
parent 33aeb603fe
commit 316025a0d8
No known key found for this signature in database
GPG Key ID: DE48307B8B0D381A
5 changed files with 105 additions and 13 deletions

View File

@ -120,7 +120,6 @@ set(INTERNAL_HEADERS
${SOURCES_DIR}/internal/catch_preprocessor_remove_parens.hpp
${SOURCES_DIR}/internal/catch_random_number_generator.hpp
${SOURCES_DIR}/internal/catch_random_seed_generation.hpp
${SOURCES_DIR}/reporters/catch_reporter_registrars.hpp
${SOURCES_DIR}/internal/catch_reporter_registry.hpp
${SOURCES_DIR}/internal/catch_reporter_spec_parser.hpp
${SOURCES_DIR}/internal/catch_result_type.hpp
@ -237,6 +236,7 @@ set(REPORTER_HEADERS
${SOURCES_DIR}/reporters/catch_reporter_helpers.hpp
${SOURCES_DIR}/reporters/catch_reporter_junit.hpp
${SOURCES_DIR}/reporters/catch_reporter_multi.hpp
${SOURCES_DIR}/reporters/catch_reporter_registrars.hpp
${SOURCES_DIR}/reporters/catch_reporter_sonarqube.hpp
${SOURCES_DIR}/reporters/catch_reporter_streaming_base.hpp
${SOURCES_DIR}/reporters/catch_reporter_tap.hpp
@ -252,6 +252,7 @@ set(REPORTER_SOURCES
${SOURCES_DIR}/reporters/catch_reporter_cumulative_base.cpp
${SOURCES_DIR}/reporters/catch_reporter_junit.cpp
${SOURCES_DIR}/reporters/catch_reporter_multi.cpp
${SOURCES_DIR}/reporters/catch_reporter_registrars.cpp
${SOURCES_DIR}/reporters/catch_reporter_sonarqube.cpp
${SOURCES_DIR}/reporters/catch_reporter_streaming_base.cpp
${SOURCES_DIR}/reporters/catch_reporter_tap.cpp

View File

@ -0,0 +1,30 @@
// Copyright Catch2 Authors
// Distributed under the Boost Software License, Version 1.0.
// (See accompanying file LICENSE_1_0.txt or copy at
// https://www.boost.org/LICENSE_1_0.txt)
// SPDX-License-Identifier: BSL-1.0
#include <catch2/reporters/catch_reporter_registrars.hpp>
#include <catch2/internal/catch_compiler_capabilities.hpp>
namespace Catch {
namespace Detail {
void registerReporterImpl( std::string const& name,
IReporterFactoryPtr reporterPtr ) {
CATCH_TRY {
getMutableRegistryHub().registerReporter(
name, CATCH_MOVE( reporterPtr ) );
}
CATCH_CATCH_ALL {
// Do not throw when constructing global objects, instead
// register the exception to be processed later
getMutableRegistryHub().registerStartupException();
}
}
} // namespace Detail
} // namespace Catch

View File

@ -12,6 +12,7 @@
#include <catch2/interfaces/catch_interfaces_reporter.hpp>
#include <catch2/interfaces/catch_interfaces_reporter_factory.hpp>
#include <catch2/internal/catch_compiler_capabilities.hpp>
#include <catch2/internal/catch_unique_name.hpp>
#include <catch2/internal/catch_unique_ptr.hpp>
#include <catch2/internal/catch_move_and_forward.hpp>
#include <catch2/internal/catch_void_type.hpp>
@ -21,6 +22,7 @@
namespace Catch {
namespace Detail {
template <typename T, typename = void>
struct has_description : std::false_type {};
@ -29,7 +31,13 @@ namespace Catch {
T,
void_t<decltype( T::getDescription() )>>
: std::true_type {};
}
//! Indirection for reporter registration, so that the error handling is
//! independent on the reporter's concrete type
void registerReporterImpl( std::string const& name,
IReporterFactoryPtr reporterPtr );
} // namespace Detail
class IEventListener;
using IEventListenerPtr = Detail::unique_ptr<IEventListener>;
@ -51,7 +59,8 @@ namespace Catch {
class ReporterRegistrar {
public:
explicit ReporterRegistrar( std::string const& name ) {
getMutableRegistryHub().registerReporter( name, Detail::make_unique<ReporterFactory<T>>() );
registerReporterImpl( name,
Detail::make_unique<ReporterFactory<T>>() );
}
};
@ -98,14 +107,21 @@ namespace Catch {
# define CATCH_REGISTER_REPORTER( name, reporterType ) \
CATCH_INTERNAL_START_WARNINGS_SUPPRESSION \
CATCH_INTERNAL_SUPPRESS_GLOBALS_WARNINGS \
namespace{ Catch::ReporterRegistrar<reporterType> catch_internal_RegistrarFor##reporterType( name ); } \
namespace { \
Catch::ReporterRegistrar<reporterType> INTERNAL_CATCH_UNIQUE_NAME( \
catch_internal_RegistrarFor )( name ); \
} \
CATCH_INTERNAL_STOP_WARNINGS_SUPPRESSION
# define CATCH_REGISTER_LISTENER( listenerType ) \
CATCH_INTERNAL_START_WARNINGS_SUPPRESSION \
CATCH_INTERNAL_SUPPRESS_GLOBALS_WARNINGS \
namespace { Catch::ListenerRegistrar<listenerType> catch_internal_RegistrarFor##listenerType(#listenerType); } \
namespace { \
Catch::ListenerRegistrar<listenerType> INTERNAL_CATCH_UNIQUE_NAME( \
catch_internal_RegistrarFor )( #listenerType ); \
} \
CATCH_INTERNAL_STOP_WARNINGS_SUPPRESSION
#else // CATCH_CONFIG_DISABLE
#define CATCH_REGISTER_REPORTER(name, reporterType)

View File

@ -421,6 +421,20 @@ set_tests_properties(
FAIL_REGULAR_EXPRESSION "error: .* already defined\\."
)
add_executable(DuplicatedReporters ${TESTS_DIR}/X35-DuplicatedReporterNames.cpp)
target_link_libraries(DuplicatedReporters PRIVATE Catch2::Catch2WithMain)
add_test(
NAME Reporters::RegistrationErrorsAreCaught
COMMAND $<TARGET_FILE:DuplicatedReporters>
)
set_tests_properties(
Reporters::RegistrationErrorsAreCaught
PROPERTIES
PASS_REGULAR_EXPRESSION "Errors occurred during startup!"
)
#add_executable(DebugBreakMacros ${TESTS_DIR}/X12-CustomDebugBreakMacro.cpp)
#target_link_libraries(DebugBreakMacros Catch2)
#add_test(NAME DebugBreakMacros COMMAND DebugBreakMacros --break)

View File

@ -0,0 +1,31 @@
// Copyright Catch2 Authors
// Distributed under the Boost Software License, Version 1.0.
// (See accompanying file LICENSE_1_0.txt or copy at
// https://www.boost.org/LICENSE_1_0.txt)
// SPDX-License-Identifier: BSL-1.0
/**\file
* Checks that reporter registration errors are caught and handled as
* startup errors, by causing a registration error by registering multiple
* reporters with the same name.
*/
#include <catch2/catch_test_macros.hpp>
#include <catch2/reporters/catch_reporter_registrars.hpp>
#include <catch2/reporters/catch_reporter_streaming_base.hpp>
namespace {
//! Trivial custom reporter for registration
class TestReporter : public Catch::StreamingReporterBase {
public:
using StreamingReporterBase::StreamingReporterBase;
static std::string getDescription() { return "X35 test reporter"; }
};
}
CATCH_REGISTER_REPORTER( "test-reporter", TestReporter )
CATCH_REGISTER_REPORTER( "test-reporter", TestReporter )