From 47200ddbee03eaf4a9d3d99d18cb692381d8f5bc Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Martin=20Ho=C5=99e=C5=88ovsk=C3=BD?= Date: Wed, 8 Apr 2026 10:26:57 +0200 Subject: [PATCH] Rework internals of CATCH_REGISTER_ENUM The old internals reached into the global hub to stash the allocation(s) for enum value -> string value there, then kept around a potentially invalid (in case the hub was cleaned up) reference into it, going through whole bunch of virtual dispatch in the process. The new internals just store the data in a static variable inside the `StringMaker` specialization. This avoids potential lifetime issues, avoids all virtual dispatch and (almost) reduces the include bloat in the main header path. The reason for (almost) there is that for full include correctness, `EnumInfo` needs `` include for `std::pair`. However, this brings in things like `std::relops`, because the std headers in C++ are dumb. As this was not included before, and instead we relied on `std::pair` existing in an internal stdlib header that we transitively included, the full include size ends up bigger than before. --- src/CMakeLists.txt | 5 +- src/catch2/catch_all.hpp | 2 +- src/catch2/catch_message.hpp | 1 + src/catch2/catch_registry_hub.cpp | 5 -- src/catch2/catch_session.cpp | 1 + src/catch2/catch_tostring.hpp | 29 ++++--- .../interfaces/catch_interfaces_all.hpp | 1 - .../catch_interfaces_enum_values_registry.hpp | 47 ----------- .../catch_interfaces_registry_hub.hpp | 1 - .../internal/catch_assertion_handler.cpp | 1 + ...alues_registry.cpp => catch_enum_info.cpp} | 28 +++---- src/catch2/internal/catch_enum_info.hpp | 48 +++++++++++ .../internal/catch_enum_values_registry.hpp | 36 -------- src/catch2/internal/catch_run_context.cpp | 1 + src/catch2/meson.build | 5 +- .../Baselines/automake.sw.approved.txt | 1 + .../Baselines/automake.sw.multi.approved.txt | 1 + .../Baselines/compact.sw.approved.txt | 27 +++--- .../Baselines/compact.sw.multi.approved.txt | 27 +++--- .../Baselines/console.std.approved.txt | 4 +- .../Baselines/console.sw.approved.txt | 59 ++++++++----- .../Baselines/console.sw.multi.approved.txt | 59 ++++++++----- .../SelfTest/Baselines/junit.sw.approved.txt | 3 +- .../Baselines/junit.sw.multi.approved.txt | 3 +- .../Baselines/sonarqube.sw.approved.txt | 11 +-- .../Baselines/sonarqube.sw.multi.approved.txt | 11 +-- tests/SelfTest/Baselines/tap.sw.approved.txt | 14 +++- .../Baselines/tap.sw.multi.approved.txt | 14 +++- .../Baselines/teamcity.sw.approved.txt | 2 + .../Baselines/teamcity.sw.multi.approved.txt | 2 + tests/SelfTest/Baselines/xml.sw.approved.txt | 67 ++++++++++----- .../Baselines/xml.sw.multi.approved.txt | 67 ++++++++++----- .../IntrospectiveTests/Reporters.tests.cpp | 1 + .../IntrospectiveTests/ToString.tests.cpp | 40 --------- .../UsageTests/EnumToString.tests.cpp | 83 ++++++++++++++++--- 35 files changed, 403 insertions(+), 304 deletions(-) delete mode 100644 src/catch2/interfaces/catch_interfaces_enum_values_registry.hpp rename src/catch2/internal/{catch_enum_values_registry.cpp => catch_enum_info.cpp} (65%) create mode 100644 src/catch2/internal/catch_enum_info.hpp delete mode 100644 src/catch2/internal/catch_enum_values_registry.hpp diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index 11089ff5..0ed64ebf 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -87,7 +87,7 @@ set(IMPL_HEADERS ${SOURCES_DIR}/internal/catch_decomposer.hpp ${SOURCES_DIR}/internal/catch_deprecation_macro.hpp ${SOURCES_DIR}/internal/catch_enforce.hpp - ${SOURCES_DIR}/internal/catch_enum_values_registry.hpp + ${SOURCES_DIR}/internal/catch_enum_info.hpp ${SOURCES_DIR}/internal/catch_errno_guard.hpp ${SOURCES_DIR}/internal/catch_exception_translator_registry.hpp ${SOURCES_DIR}/internal/catch_fatal_condition_handler.hpp @@ -181,7 +181,7 @@ set(IMPL_SOURCES ${SOURCES_DIR}/internal/catch_debugger.cpp ${SOURCES_DIR}/internal/catch_decomposer.cpp ${SOURCES_DIR}/internal/catch_enforce.cpp - ${SOURCES_DIR}/internal/catch_enum_values_registry.cpp + ${SOURCES_DIR}/internal/catch_enum_info.cpp ${SOURCES_DIR}/internal/catch_errno_guard.cpp ${SOURCES_DIR}/internal/catch_exception_translator_registry.cpp ${SOURCES_DIR}/internal/catch_fatal_condition_handler.cpp @@ -227,7 +227,6 @@ set(INTERFACE_HEADERS ${SOURCES_DIR}/interfaces/catch_interfaces_all.hpp ${SOURCES_DIR}/interfaces/catch_interfaces_capture.hpp ${SOURCES_DIR}/interfaces/catch_interfaces_config.hpp - ${SOURCES_DIR}/interfaces/catch_interfaces_enum_values_registry.hpp ${SOURCES_DIR}/interfaces/catch_interfaces_exception.hpp ${SOURCES_DIR}/interfaces/catch_interfaces_generatortracker.hpp ${SOURCES_DIR}/interfaces/catch_interfaces_registry_hub.hpp diff --git a/src/catch2/catch_all.hpp b/src/catch2/catch_all.hpp index 97226dd1..82b11405 100644 --- a/src/catch2/catch_all.hpp +++ b/src/catch2/catch_all.hpp @@ -68,7 +68,7 @@ #include #include #include -#include +#include #include #include #include diff --git a/src/catch2/catch_message.hpp b/src/catch2/catch_message.hpp index 4958716d..4582654f 100644 --- a/src/catch2/catch_message.hpp +++ b/src/catch2/catch_message.hpp @@ -13,6 +13,7 @@ #include #include #include +#include #include #include diff --git a/src/catch2/catch_registry_hub.cpp b/src/catch2/catch_registry_hub.cpp index 925468fa..25aecdde 100644 --- a/src/catch2/catch_registry_hub.cpp +++ b/src/catch2/catch_registry_hub.cpp @@ -15,7 +15,6 @@ #include #include #include -#include #include #include #include @@ -72,9 +71,6 @@ namespace Catch { CATCH_INTERNAL_ERROR("Attempted to register active exception under CATCH_CONFIG_DISABLE_EXCEPTIONS!"); #endif } - IMutableEnumValuesRegistry& getMutableEnumValuesRegistry() override { - return m_enumValuesRegistry; - } private: TestRegistry m_testCaseRegistry; @@ -82,7 +78,6 @@ namespace Catch { ExceptionTranslatorRegistry m_exceptionTranslatorRegistry; TagAliasRegistry m_tagAliasRegistry; StartupExceptionRegistry m_exceptionRegistry; - Detail::EnumValuesRegistry m_enumValuesRegistry; }; } diff --git a/src/catch2/catch_session.cpp b/src/catch2/catch_session.cpp index 042b7f4d..0487fe75 100644 --- a/src/catch2/catch_session.cpp +++ b/src/catch2/catch_session.cpp @@ -21,6 +21,7 @@ #include #include #include +#include #include #include #include diff --git a/src/catch2/catch_tostring.hpp b/src/catch2/catch_tostring.hpp index b005212f..16c4c496 100644 --- a/src/catch2/catch_tostring.hpp +++ b/src/catch2/catch_tostring.hpp @@ -18,7 +18,8 @@ #include #include #include -#include +#include +#include #ifdef CATCH_CONFIG_CPP17_STRING_VIEW #include @@ -630,17 +631,21 @@ struct ratio_string { }; } -#include - -#define INTERNAL_CATCH_REGISTER_ENUM( enumName, ... ) \ -namespace Catch { \ - template<> struct StringMaker { \ - static std::string convert( enumName value ) { \ - static const auto& enumInfo = ::Catch::getMutableRegistryHub().getMutableEnumValuesRegistry().registerEnum( #enumName, #__VA_ARGS__, { __VA_ARGS__ } ); \ - return static_cast(enumInfo.lookup( static_cast( value ) )); \ - } \ - }; \ -} +#define INTERNAL_CATCH_REGISTER_ENUM( enumName, ... ) \ + namespace Catch { \ + template <> \ + struct StringMaker { \ + static std::string convert( enumName value ) { \ + CATCH_INTERNAL_START_WARNINGS_SUPPRESSION \ + CATCH_INTERNAL_SUPPRESS_GLOBALS_WARNINGS \ + static const auto enumInfo = ::Catch::Detail::makeEnumInfo( \ + #enumName, #__VA_ARGS__, { __VA_ARGS__ } ); \ + CATCH_INTERNAL_STOP_WARNINGS_SUPPRESSION \ + return static_cast( \ + enumInfo.lookup( static_cast( value ) ) ); \ + } \ + }; \ + } #define CATCH_REGISTER_ENUM( enumName, ... ) INTERNAL_CATCH_REGISTER_ENUM( enumName, __VA_ARGS__ ) diff --git a/src/catch2/interfaces/catch_interfaces_all.hpp b/src/catch2/interfaces/catch_interfaces_all.hpp index a99fdcdc..87eb259b 100644 --- a/src/catch2/interfaces/catch_interfaces_all.hpp +++ b/src/catch2/interfaces/catch_interfaces_all.hpp @@ -24,7 +24,6 @@ #include #include -#include #include #include #include diff --git a/src/catch2/interfaces/catch_interfaces_enum_values_registry.hpp b/src/catch2/interfaces/catch_interfaces_enum_values_registry.hpp deleted file mode 100644 index 38b052d9..00000000 --- a/src/catch2/interfaces/catch_interfaces_enum_values_registry.hpp +++ /dev/null @@ -1,47 +0,0 @@ - -// 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 -#ifndef CATCH_INTERFACES_ENUM_VALUES_REGISTRY_HPP_INCLUDED -#define CATCH_INTERFACES_ENUM_VALUES_REGISTRY_HPP_INCLUDED - -#include - -#include - -namespace Catch { - - namespace Detail { - struct EnumInfo { - StringRef m_name; - std::vector> m_values; - - ~EnumInfo(); - - StringRef lookup( int value ) const; - }; - } // namespace Detail - - class IMutableEnumValuesRegistry { - public: - virtual ~IMutableEnumValuesRegistry(); // = default; - - virtual Detail::EnumInfo const& registerEnum( StringRef enumName, StringRef allEnums, std::vector const& values ) = 0; - - template - Detail::EnumInfo const& registerEnum( StringRef enumName, StringRef allEnums, std::initializer_list values ) { - static_assert(sizeof(int) >= sizeof(E), "Cannot serialize enum to int"); - std::vector intValues; - intValues.reserve( values.size() ); - for( auto enumValue : values ) - intValues.push_back( static_cast( enumValue ) ); - return registerEnum( enumName, allEnums, intValues ); - } - }; - -} // Catch - -#endif // CATCH_INTERFACES_ENUM_VALUES_REGISTRY_HPP_INCLUDED diff --git a/src/catch2/interfaces/catch_interfaces_registry_hub.hpp b/src/catch2/interfaces/catch_interfaces_registry_hub.hpp index 113f223e..3695a192 100644 --- a/src/catch2/interfaces/catch_interfaces_registry_hub.hpp +++ b/src/catch2/interfaces/catch_interfaces_registry_hub.hpp @@ -53,7 +53,6 @@ namespace Catch { virtual void registerTranslator( Detail::unique_ptr&& translator ) = 0; virtual void registerTagAlias( std::string const& alias, std::string const& tag, SourceLineInfo const& lineInfo ) = 0; virtual void registerStartupException() noexcept = 0; - virtual IMutableEnumValuesRegistry& getMutableEnumValuesRegistry() = 0; }; IRegistryHub const& getRegistryHub(); diff --git a/src/catch2/internal/catch_assertion_handler.cpp b/src/catch2/internal/catch_assertion_handler.cpp index a0fcfcb4..5a4806e9 100644 --- a/src/catch2/internal/catch_assertion_handler.cpp +++ b/src/catch2/internal/catch_assertion_handler.cpp @@ -8,6 +8,7 @@ #include #include #include +#include #include #include #include diff --git a/src/catch2/internal/catch_enum_values_registry.cpp b/src/catch2/internal/catch_enum_info.cpp similarity index 65% rename from src/catch2/internal/catch_enum_values_registry.cpp rename to src/catch2/internal/catch_enum_info.cpp index a94b6088..0793abd9 100644 --- a/src/catch2/internal/catch_enum_values_registry.cpp +++ b/src/catch2/internal/catch_enum_info.cpp @@ -5,15 +5,14 @@ // https://www.boost.org/LICENSE_1_0.txt) // SPDX-License-Identifier: BSL-1.0 -#include + +#include #include #include namespace Catch { - IMutableEnumValuesRegistry::~IMutableEnumValuesRegistry() = default; - namespace Detail { namespace { @@ -39,9 +38,7 @@ namespace Catch { return parsed; } - EnumInfo::~EnumInfo() = default; - - StringRef EnumInfo::lookup( int value ) const { + StringRef EnumInfo::lookup( int64_t value ) const { for( auto const& valueToName : m_values ) { if( valueToName.first == value ) return valueToName.second; @@ -49,25 +46,20 @@ namespace Catch { return "{** unexpected enum value **}"_sr; } - Catch::Detail::unique_ptr makeEnumInfo( StringRef enumName, StringRef allValueNames, std::vector const& values ) { - auto enumInfo = Catch::Detail::make_unique(); - enumInfo->m_name = enumName; - enumInfo->m_values.reserve( values.size() ); + EnumInfo makeEnumInfo( StringRef enumName, StringRef allValueNames, std::vector const& values ) { + EnumInfo enumInfo; + enumInfo.m_name = enumName; + enumInfo.m_values.reserve( values.size() ); const auto valueNames = Catch::Detail::parseEnums( allValueNames ); assert( valueNames.size() == values.size() ); - std::size_t i = 0; - for( auto value : values ) - enumInfo->m_values.emplace_back(value, valueNames[i++]); + for (size_t i = 0; i < values.size(); ++i) { + enumInfo.m_values.emplace_back( values[i], valueNames[i] ); + } return enumInfo; } - EnumInfo const& EnumValuesRegistry::registerEnum( StringRef enumName, StringRef allValueNames, std::vector const& values ) { - m_enumInfos.push_back(makeEnumInfo(enumName, allValueNames, values)); - return *m_enumInfos.back(); - } - } // Detail } // Catch diff --git a/src/catch2/internal/catch_enum_info.hpp b/src/catch2/internal/catch_enum_info.hpp new file mode 100644 index 00000000..b3036a82 --- /dev/null +++ b/src/catch2/internal/catch_enum_info.hpp @@ -0,0 +1,48 @@ + +// 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 +#ifndef CATCH_ENUM_INFO_HPP_INCLUDED +#define CATCH_ENUM_INFO_HPP_INCLUDED + +#include + +#include +#include +#include + +namespace Catch { + namespace Detail { + + struct EnumInfo { + StringRef m_name; + std::vector> m_values; + + StringRef lookup( int64_t value ) const; + }; + + EnumInfo makeEnumInfo( StringRef enumName, + StringRef allValueNames, + std::vector const& values ); + template + Detail::EnumInfo makeEnumInfo( StringRef enumName, + StringRef allEnums, + std::initializer_list values ) { + static_assert( sizeof( int64_t ) >= sizeof( E ), + "Cannot serialize enum to int64_t" ); + std::vector intValues; + intValues.reserve( values.size() ); + for ( auto enumValue : values ) + intValues.push_back( static_cast( enumValue ) ); + return makeEnumInfo( enumName, allEnums, intValues ); + } + + std::vector parseEnums( StringRef enums ); + + } // namespace Detail +} // namespace Catch + +#endif // CATCH_ENUM_INFO_HPP_INCLUDED diff --git a/src/catch2/internal/catch_enum_values_registry.hpp b/src/catch2/internal/catch_enum_values_registry.hpp deleted file mode 100644 index 7b5e7a72..00000000 --- a/src/catch2/internal/catch_enum_values_registry.hpp +++ /dev/null @@ -1,36 +0,0 @@ - -// 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 -#ifndef CATCH_ENUM_VALUES_REGISTRY_HPP_INCLUDED -#define CATCH_ENUM_VALUES_REGISTRY_HPP_INCLUDED - -#include -#include -#include - -#include - -namespace Catch { - - namespace Detail { - - Catch::Detail::unique_ptr makeEnumInfo( StringRef enumName, StringRef allValueNames, std::vector const& values ); - - class EnumValuesRegistry final : public IMutableEnumValuesRegistry { - - std::vector> m_enumInfos; - - EnumInfo const& registerEnum( StringRef enumName, StringRef allValueNames, std::vector const& values) override; - }; - - std::vector parseEnums( StringRef enums ); - - } // Detail - -} // Catch - -#endif // CATCH_ENUM_VALUES_REGISTRY_HPP_INCLUDED diff --git a/src/catch2/internal/catch_run_context.cpp b/src/catch2/internal/catch_run_context.cpp index 547ff9d8..e7e22c58 100644 --- a/src/catch2/internal/catch_run_context.cpp +++ b/src/catch2/internal/catch_run_context.cpp @@ -11,6 +11,7 @@ #include #include #include +#include #include #include #include diff --git a/src/catch2/meson.build b/src/catch2/meson.build index f491c602..94e0496a 100644 --- a/src/catch2/meson.build +++ b/src/catch2/meson.build @@ -65,7 +65,6 @@ internal_headers = [ 'interfaces/catch_interfaces_all.hpp', 'interfaces/catch_interfaces_capture.hpp', 'interfaces/catch_interfaces_config.hpp', - 'interfaces/catch_interfaces_enum_values_registry.hpp', 'interfaces/catch_interfaces_exception.hpp', 'interfaces/catch_interfaces_generatortracker.hpp', 'interfaces/catch_interfaces_registry_hub.hpp', @@ -95,7 +94,7 @@ internal_headers = [ 'internal/catch_decomposer.hpp', 'internal/catch_deprecation_macro.hpp', 'internal/catch_enforce.hpp', - 'internal/catch_enum_values_registry.hpp', + 'internal/catch_enum_info.hpp', 'internal/catch_errno_guard.hpp', 'internal/catch_exception_translator_registry.hpp', 'internal/catch_fatal_condition_handler.hpp', @@ -224,7 +223,7 @@ internal_sources = files( 'internal/catch_debugger.cpp', 'internal/catch_decomposer.cpp', 'internal/catch_enforce.cpp', - 'internal/catch_enum_values_registry.cpp', + 'internal/catch_enum_info.cpp', 'internal/catch_errno_guard.cpp', 'internal/catch_exception_translator_registry.cpp', 'internal/catch_fatal_condition_handler.cpp', diff --git a/tests/SelfTest/Baselines/automake.sw.approved.txt b/tests/SelfTest/Baselines/automake.sw.approved.txt index f5c2fa97..5018a19a 100644 --- a/tests/SelfTest/Baselines/automake.sw.approved.txt +++ b/tests/SelfTest/Baselines/automake.sw.approved.txt @@ -144,6 +144,7 @@ Nor would this :test-result: SKIP Empty generators can SKIP in constructor :test-result: PASS Empty stream name opens cout stream :test-result: FAIL EndsWith string matcher +:test-result: PASS Enum backed by larger underlying type :test-result: PASS Enums can quickly have stringification enabled using CATCH_REGISTER_ENUM :test-result: PASS Enums in namespaces can quickly have stringification enabled using CATCH_REGISTER_ENUM :test-result: PASS Epsilon only applies to Approx's value diff --git a/tests/SelfTest/Baselines/automake.sw.multi.approved.txt b/tests/SelfTest/Baselines/automake.sw.multi.approved.txt index 973e2f53..4f9a9441 100644 --- a/tests/SelfTest/Baselines/automake.sw.multi.approved.txt +++ b/tests/SelfTest/Baselines/automake.sw.multi.approved.txt @@ -142,6 +142,7 @@ :test-result: SKIP Empty generators can SKIP in constructor :test-result: PASS Empty stream name opens cout stream :test-result: FAIL EndsWith string matcher +:test-result: PASS Enum backed by larger underlying type :test-result: PASS Enums can quickly have stringification enabled using CATCH_REGISTER_ENUM :test-result: PASS Enums in namespaces can quickly have stringification enabled using CATCH_REGISTER_ENUM :test-result: PASS Epsilon only applies to Approx's value diff --git a/tests/SelfTest/Baselines/compact.sw.approved.txt b/tests/SelfTest/Baselines/compact.sw.approved.txt index e4258ecb..cb90a0f5 100644 --- a/tests/SelfTest/Baselines/compact.sw.approved.txt +++ b/tests/SelfTest/Baselines/compact.sw.approved.txt @@ -576,15 +576,18 @@ Approx.tests.cpp:: passed: 101.000001 != Approx(100).epsilon(0.01) Approx.tests.cpp:: passed: std::pow(10, -5) != Approx(std::pow(10, -7)) for: 0.00001 != Approx( 0.0000001 ) Message.tests.cpp:: passed: true with 1 message: 'a' Message.tests.cpp:: failed: false with 1 message: 'b' -ToString.tests.cpp:: passed: enumInfo->lookup(0) == "Value1" for: Value1 == "Value1" -ToString.tests.cpp:: passed: enumInfo->lookup(1) == "Value2" for: Value2 == "Value2" -ToString.tests.cpp:: passed: enumInfo->lookup(3) == "{** unexpected enum value **}" for: {** unexpected enum value **} +EnumToString.tests.cpp:: passed: enumInfo.lookup(0) == "Value1" for: Value1 == "Value1" +EnumToString.tests.cpp:: passed: enumInfo.lookup(1) == "Value2" for: Value2 == "Value2" +EnumToString.tests.cpp:: passed: enumInfo.lookup(3) == "{** unexpected enum value **}" for: {** unexpected enum value **} == "{** unexpected enum value **}" Skip.tests.cpp:: skipped: 'This generator is empty' Stream.tests.cpp:: passed: Catch::makeStream( "" )->isConsole() for: true Matchers.tests.cpp:: failed: testStringForMatching(), EndsWith( "Substring" ) for: "this string contains 'abc' as a substring" ends with: "Substring" Matchers.tests.cpp:: failed: testStringForMatching(), EndsWith( "this", Catch::CaseSensitive::No ) for: "this string contains 'abc' as a substring" ends with: "this" (case insensitive) +EnumToString.tests.cpp:: passed: stringify( LargeEnum::Flag1 ) == "Flag1" for: "Flag1" == "Flag1" +EnumToString.tests.cpp:: passed: stringify( LargeEnum::Flag2 ) == "Flag2" for: "Flag2" == "Flag2" +EnumToString.tests.cpp:: passed: stringify( LargeEnum::Flag5 ) == "Flag5" for: "Flag5" == "Flag5" EnumToString.tests.cpp:: passed: stringify( EnumClass3::Value1 ) == "Value1" for: "Value1" == "Value1" EnumToString.tests.cpp:: passed: stringify( EnumClass3::Value2 ) == "Value2" for: "Value2" == "Value2" EnumToString.tests.cpp:: passed: stringify( EnumClass3::Value3 ) == "Value3" for: "Value3" == "Value3" @@ -2755,13 +2758,13 @@ Tricky.tests.cpp:: passed: ptr.get() == 0 for: 0 == 0 ToStringPair.tests.cpp:: passed: ::Catch::Detail::stringify( pair ) == "{ { 42, \"Arthur\" }, { \"Ford\", 24 } }" for: "{ { 42, "Arthur" }, { "Ford", 24 } }" == "{ { 42, "Arthur" }, { "Ford", 24 } }" -ToString.tests.cpp:: passed: parseEnums( "" ), Equals( std::vector{} ) for: { } Equals: { } -ToString.tests.cpp:: passed: parseEnums( "ClassName::EnumName::Value1" ), Equals(std::vector{"Value1"} ) for: { Value1 } Equals: { Value1 } -ToString.tests.cpp:: passed: parseEnums( "Value1" ), Equals( std::vector{"Value1"} ) for: { Value1 } Equals: { Value1 } -ToString.tests.cpp:: passed: parseEnums( "EnumName::Value1" ), Equals(std::vector{"Value1"} ) for: { Value1 } Equals: { Value1 } -ToString.tests.cpp:: passed: parseEnums( "ClassName::EnumName::Value1, ClassName::EnumName::Value2" ), Equals( std::vector{"Value1", "Value2"} ) for: { Value1, Value2 } Equals: { Value1, Value2 } -ToString.tests.cpp:: passed: parseEnums( "ClassName::EnumName::Value1, ClassName::EnumName::Value2, ClassName::EnumName::Value3" ), Equals( std::vector{"Value1", "Value2", "Value3"} ) for: { Value1, Value2, Value3 } Equals: { Value1, Value2, Value3 } -ToString.tests.cpp:: passed: parseEnums( "ClassName::EnumName::Value1,ClassName::EnumName::Value2 , ClassName::EnumName::Value3" ), Equals( std::vector{"Value1", "Value2", "Value3"} ) for: { Value1, Value2, Value3 } Equals: { Value1, Value2, Value3 } +EnumToString.tests.cpp:: passed: parseEnums( "" ), Equals( std::vector{} ) for: { } Equals: { } +EnumToString.tests.cpp:: passed: parseEnums( "ClassName::EnumName::Value1" ), Equals(std::vector{"Value1"} ) for: { Value1 } Equals: { Value1 } +EnumToString.tests.cpp:: passed: parseEnums( "Value1" ), Equals( std::vector{"Value1"} ) for: { Value1 } Equals: { Value1 } +EnumToString.tests.cpp:: passed: parseEnums( "EnumName::Value1" ), Equals(std::vector{"Value1"} ) for: { Value1 } Equals: { Value1 } +EnumToString.tests.cpp:: passed: parseEnums( "ClassName::EnumName::Value1, ClassName::EnumName::Value2" ), Equals( std::vector{"Value1", "Value2"} ) for: { Value1, Value2 } Equals: { Value1, Value2 } +EnumToString.tests.cpp:: passed: parseEnums( "ClassName::EnumName::Value1, ClassName::EnumName::Value2, ClassName::EnumName::Value3" ), Equals( std::vector{"Value1", "Value2", "Value3"} ) for: { Value1, Value2, Value3 } Equals: { Value1, Value2, Value3 } +EnumToString.tests.cpp:: passed: parseEnums( "ClassName::EnumName::Value1,ClassName::EnumName::Value2 , ClassName::EnumName::Value3" ), Equals( std::vector{"Value1", "Value2", "Value3"} ) for: { Value1, Value2, Value3 } Equals: { Value1, Value2, Value3 } Tricky.tests.cpp:: passed: p == 0 for: 0 == 0 Message.tests.cpp:: passed: true with 1 message: 'this MAY be seen IF info is printed for passing assertions' Message.tests.cpp:: failed: false with 2 messages: 'this SHOULD be seen' and 'this SHOULD also be seen' @@ -2997,7 +3000,7 @@ InternalBenchmark.tests.cpp:: passed: med == 18. for: 18.0 == 18.0 InternalBenchmark.tests.cpp:: passed: q3 == 23. for: 23.0 == 23.0 Misc.tests.cpp:: passed: Misc.tests.cpp:: passed: -test cases: 450 | 330 passed | 96 failed | 6 skipped | 18 failed as expected -assertions: 2413 | 2212 passed | 158 failed | 43 failed as expected +test cases: 451 | 331 passed | 96 failed | 6 skipped | 18 failed as expected +assertions: 2416 | 2215 passed | 158 failed | 43 failed as expected diff --git a/tests/SelfTest/Baselines/compact.sw.multi.approved.txt b/tests/SelfTest/Baselines/compact.sw.multi.approved.txt index 19309e5a..39c260af 100644 --- a/tests/SelfTest/Baselines/compact.sw.multi.approved.txt +++ b/tests/SelfTest/Baselines/compact.sw.multi.approved.txt @@ -574,15 +574,18 @@ Approx.tests.cpp:: passed: 101.000001 != Approx(100).epsilon(0.01) Approx.tests.cpp:: passed: std::pow(10, -5) != Approx(std::pow(10, -7)) for: 0.00001 != Approx( 0.0000001 ) Message.tests.cpp:: passed: true with 1 message: 'a' Message.tests.cpp:: failed: false with 1 message: 'b' -ToString.tests.cpp:: passed: enumInfo->lookup(0) == "Value1" for: Value1 == "Value1" -ToString.tests.cpp:: passed: enumInfo->lookup(1) == "Value2" for: Value2 == "Value2" -ToString.tests.cpp:: passed: enumInfo->lookup(3) == "{** unexpected enum value **}" for: {** unexpected enum value **} +EnumToString.tests.cpp:: passed: enumInfo.lookup(0) == "Value1" for: Value1 == "Value1" +EnumToString.tests.cpp:: passed: enumInfo.lookup(1) == "Value2" for: Value2 == "Value2" +EnumToString.tests.cpp:: passed: enumInfo.lookup(3) == "{** unexpected enum value **}" for: {** unexpected enum value **} == "{** unexpected enum value **}" Skip.tests.cpp:: skipped: 'This generator is empty' Stream.tests.cpp:: passed: Catch::makeStream( "" )->isConsole() for: true Matchers.tests.cpp:: failed: testStringForMatching(), EndsWith( "Substring" ) for: "this string contains 'abc' as a substring" ends with: "Substring" Matchers.tests.cpp:: failed: testStringForMatching(), EndsWith( "this", Catch::CaseSensitive::No ) for: "this string contains 'abc' as a substring" ends with: "this" (case insensitive) +EnumToString.tests.cpp:: passed: stringify( LargeEnum::Flag1 ) == "Flag1" for: "Flag1" == "Flag1" +EnumToString.tests.cpp:: passed: stringify( LargeEnum::Flag2 ) == "Flag2" for: "Flag2" == "Flag2" +EnumToString.tests.cpp:: passed: stringify( LargeEnum::Flag5 ) == "Flag5" for: "Flag5" == "Flag5" EnumToString.tests.cpp:: passed: stringify( EnumClass3::Value1 ) == "Value1" for: "Value1" == "Value1" EnumToString.tests.cpp:: passed: stringify( EnumClass3::Value2 ) == "Value2" for: "Value2" == "Value2" EnumToString.tests.cpp:: passed: stringify( EnumClass3::Value3 ) == "Value3" for: "Value3" == "Value3" @@ -2744,13 +2747,13 @@ Tricky.tests.cpp:: passed: ptr.get() == 0 for: 0 == 0 ToStringPair.tests.cpp:: passed: ::Catch::Detail::stringify( pair ) == "{ { 42, \"Arthur\" }, { \"Ford\", 24 } }" for: "{ { 42, "Arthur" }, { "Ford", 24 } }" == "{ { 42, "Arthur" }, { "Ford", 24 } }" -ToString.tests.cpp:: passed: parseEnums( "" ), Equals( std::vector{} ) for: { } Equals: { } -ToString.tests.cpp:: passed: parseEnums( "ClassName::EnumName::Value1" ), Equals(std::vector{"Value1"} ) for: { Value1 } Equals: { Value1 } -ToString.tests.cpp:: passed: parseEnums( "Value1" ), Equals( std::vector{"Value1"} ) for: { Value1 } Equals: { Value1 } -ToString.tests.cpp:: passed: parseEnums( "EnumName::Value1" ), Equals(std::vector{"Value1"} ) for: { Value1 } Equals: { Value1 } -ToString.tests.cpp:: passed: parseEnums( "ClassName::EnumName::Value1, ClassName::EnumName::Value2" ), Equals( std::vector{"Value1", "Value2"} ) for: { Value1, Value2 } Equals: { Value1, Value2 } -ToString.tests.cpp:: passed: parseEnums( "ClassName::EnumName::Value1, ClassName::EnumName::Value2, ClassName::EnumName::Value3" ), Equals( std::vector{"Value1", "Value2", "Value3"} ) for: { Value1, Value2, Value3 } Equals: { Value1, Value2, Value3 } -ToString.tests.cpp:: passed: parseEnums( "ClassName::EnumName::Value1,ClassName::EnumName::Value2 , ClassName::EnumName::Value3" ), Equals( std::vector{"Value1", "Value2", "Value3"} ) for: { Value1, Value2, Value3 } Equals: { Value1, Value2, Value3 } +EnumToString.tests.cpp:: passed: parseEnums( "" ), Equals( std::vector{} ) for: { } Equals: { } +EnumToString.tests.cpp:: passed: parseEnums( "ClassName::EnumName::Value1" ), Equals(std::vector{"Value1"} ) for: { Value1 } Equals: { Value1 } +EnumToString.tests.cpp:: passed: parseEnums( "Value1" ), Equals( std::vector{"Value1"} ) for: { Value1 } Equals: { Value1 } +EnumToString.tests.cpp:: passed: parseEnums( "EnumName::Value1" ), Equals(std::vector{"Value1"} ) for: { Value1 } Equals: { Value1 } +EnumToString.tests.cpp:: passed: parseEnums( "ClassName::EnumName::Value1, ClassName::EnumName::Value2" ), Equals( std::vector{"Value1", "Value2"} ) for: { Value1, Value2 } Equals: { Value1, Value2 } +EnumToString.tests.cpp:: passed: parseEnums( "ClassName::EnumName::Value1, ClassName::EnumName::Value2, ClassName::EnumName::Value3" ), Equals( std::vector{"Value1", "Value2", "Value3"} ) for: { Value1, Value2, Value3 } Equals: { Value1, Value2, Value3 } +EnumToString.tests.cpp:: passed: parseEnums( "ClassName::EnumName::Value1,ClassName::EnumName::Value2 , ClassName::EnumName::Value3" ), Equals( std::vector{"Value1", "Value2", "Value3"} ) for: { Value1, Value2, Value3 } Equals: { Value1, Value2, Value3 } Tricky.tests.cpp:: passed: p == 0 for: 0 == 0 Message.tests.cpp:: passed: true with 1 message: 'this MAY be seen IF info is printed for passing assertions' Message.tests.cpp:: failed: false with 2 messages: 'this SHOULD be seen' and 'this SHOULD also be seen' @@ -2986,7 +2989,7 @@ InternalBenchmark.tests.cpp:: passed: med == 18. for: 18.0 == 18.0 InternalBenchmark.tests.cpp:: passed: q3 == 23. for: 23.0 == 23.0 Misc.tests.cpp:: passed: Misc.tests.cpp:: passed: -test cases: 450 | 330 passed | 96 failed | 6 skipped | 18 failed as expected -assertions: 2413 | 2212 passed | 158 failed | 43 failed as expected +test cases: 451 | 331 passed | 96 failed | 6 skipped | 18 failed as expected +assertions: 2416 | 2215 passed | 158 failed | 43 failed as expected diff --git a/tests/SelfTest/Baselines/console.std.approved.txt b/tests/SelfTest/Baselines/console.std.approved.txt index c890017e..78c3d640 100644 --- a/tests/SelfTest/Baselines/console.std.approved.txt +++ b/tests/SelfTest/Baselines/console.std.approved.txt @@ -1743,6 +1743,6 @@ due to unexpected exception with message: Why would you throw a std::string? =============================================================================== -test cases: 450 | 348 passed | 76 failed | 7 skipped | 19 failed as expected -assertions: 2391 | 2212 passed | 136 failed | 43 failed as expected +test cases: 451 | 349 passed | 76 failed | 7 skipped | 19 failed as expected +assertions: 2394 | 2215 passed | 136 failed | 43 failed as expected diff --git a/tests/SelfTest/Baselines/console.sw.approved.txt b/tests/SelfTest/Baselines/console.sw.approved.txt index 9024aa34..add1eaaf 100644 --- a/tests/SelfTest/Baselines/console.sw.approved.txt +++ b/tests/SelfTest/Baselines/console.sw.approved.txt @@ -4241,21 +4241,21 @@ with message: ------------------------------------------------------------------------------- Directly creating an EnumInfo ------------------------------------------------------------------------------- -ToString.tests.cpp: +EnumToString.tests.cpp: ............................................................................... -ToString.tests.cpp:: PASSED: - CHECK( enumInfo->lookup(0) == "Value1" ) +EnumToString.tests.cpp:: PASSED: + CHECK( enumInfo.lookup(0) == "Value1" ) with expansion: Value1 == "Value1" -ToString.tests.cpp:: PASSED: - CHECK( enumInfo->lookup(1) == "Value2" ) +EnumToString.tests.cpp:: PASSED: + CHECK( enumInfo.lookup(1) == "Value2" ) with expansion: Value2 == "Value2" -ToString.tests.cpp:: PASSED: - CHECK( enumInfo->lookup(3) == "{** unexpected enum value **}" ) +EnumToString.tests.cpp:: PASSED: + CHECK( enumInfo.lookup(3) == "{** unexpected enum value **}" ) with expansion: {** unexpected enum value **} == @@ -4299,6 +4299,27 @@ with expansion: "this string contains 'abc' as a substring" ends with: "this" (case insensitive) +------------------------------------------------------------------------------- +Enum backed by larger underlying type +------------------------------------------------------------------------------- +EnumToString.tests.cpp: +............................................................................... + +EnumToString.tests.cpp:: PASSED: + REQUIRE( stringify( LargeEnum::Flag1 ) == "Flag1" ) +with expansion: + "Flag1" == "Flag1" + +EnumToString.tests.cpp:: PASSED: + REQUIRE( stringify( LargeEnum::Flag2 ) == "Flag2" ) +with expansion: + "Flag2" == "Flag2" + +EnumToString.tests.cpp:: PASSED: + REQUIRE( stringify( LargeEnum::Flag5 ) == "Flag5" ) +with expansion: + "Flag5" == "Flag5" + ------------------------------------------------------------------------------- Enums can quickly have stringification enabled using CATCH_REGISTER_ENUM ------------------------------------------------------------------------------- @@ -18383,10 +18404,10 @@ with expansion: parseEnums No enums ------------------------------------------------------------------------------- -ToString.tests.cpp: +EnumToString.tests.cpp: ............................................................................... -ToString.tests.cpp:: PASSED: +EnumToString.tests.cpp:: PASSED: CHECK_THAT( parseEnums( "" ), Equals( std::vector{} ) ) with expansion: { } Equals: { } @@ -18395,20 +18416,20 @@ with expansion: parseEnums One enum value ------------------------------------------------------------------------------- -ToString.tests.cpp: +EnumToString.tests.cpp: ............................................................................... -ToString.tests.cpp:: PASSED: +EnumToString.tests.cpp:: PASSED: CHECK_THAT( parseEnums( "ClassName::EnumName::Value1" ), Equals(std::vector{"Value1"} ) ) with expansion: { Value1 } Equals: { Value1 } -ToString.tests.cpp:: PASSED: +EnumToString.tests.cpp:: PASSED: CHECK_THAT( parseEnums( "Value1" ), Equals( std::vector{"Value1"} ) ) with expansion: { Value1 } Equals: { Value1 } -ToString.tests.cpp:: PASSED: +EnumToString.tests.cpp:: PASSED: CHECK_THAT( parseEnums( "EnumName::Value1" ), Equals(std::vector{"Value1"} ) ) with expansion: { Value1 } Equals: { Value1 } @@ -18417,20 +18438,20 @@ with expansion: parseEnums Multiple enum values ------------------------------------------------------------------------------- -ToString.tests.cpp: +EnumToString.tests.cpp: ............................................................................... -ToString.tests.cpp:: PASSED: +EnumToString.tests.cpp:: PASSED: CHECK_THAT( parseEnums( "ClassName::EnumName::Value1, ClassName::EnumName::Value2" ), Equals( std::vector{"Value1", "Value2"} ) ) with expansion: { Value1, Value2 } Equals: { Value1, Value2 } -ToString.tests.cpp:: PASSED: +EnumToString.tests.cpp:: PASSED: CHECK_THAT( parseEnums( "ClassName::EnumName::Value1, ClassName::EnumName::Value2, ClassName::EnumName::Value3" ), Equals( std::vector{"Value1", "Value2", "Value3"} ) ) with expansion: { Value1, Value2, Value3 } Equals: { Value1, Value2, Value3 } -ToString.tests.cpp:: PASSED: +EnumToString.tests.cpp:: PASSED: CHECK_THAT( parseEnums( "ClassName::EnumName::Value1,ClassName::EnumName::Value2 , ClassName::EnumName::Value3" ), Equals( std::vector{"Value1", "Value2", "Value3"} ) ) with expansion: { Value1, Value2, Value3 } Equals: { Value1, Value2, Value3 } @@ -20113,6 +20134,6 @@ Misc.tests.cpp: Misc.tests.cpp:: PASSED: =============================================================================== -test cases: 450 | 330 passed | 96 failed | 6 skipped | 18 failed as expected -assertions: 2413 | 2212 passed | 158 failed | 43 failed as expected +test cases: 451 | 331 passed | 96 failed | 6 skipped | 18 failed as expected +assertions: 2416 | 2215 passed | 158 failed | 43 failed as expected diff --git a/tests/SelfTest/Baselines/console.sw.multi.approved.txt b/tests/SelfTest/Baselines/console.sw.multi.approved.txt index f4c6dc10..07195577 100644 --- a/tests/SelfTest/Baselines/console.sw.multi.approved.txt +++ b/tests/SelfTest/Baselines/console.sw.multi.approved.txt @@ -4239,21 +4239,21 @@ with message: ------------------------------------------------------------------------------- Directly creating an EnumInfo ------------------------------------------------------------------------------- -ToString.tests.cpp: +EnumToString.tests.cpp: ............................................................................... -ToString.tests.cpp:: PASSED: - CHECK( enumInfo->lookup(0) == "Value1" ) +EnumToString.tests.cpp:: PASSED: + CHECK( enumInfo.lookup(0) == "Value1" ) with expansion: Value1 == "Value1" -ToString.tests.cpp:: PASSED: - CHECK( enumInfo->lookup(1) == "Value2" ) +EnumToString.tests.cpp:: PASSED: + CHECK( enumInfo.lookup(1) == "Value2" ) with expansion: Value2 == "Value2" -ToString.tests.cpp:: PASSED: - CHECK( enumInfo->lookup(3) == "{** unexpected enum value **}" ) +EnumToString.tests.cpp:: PASSED: + CHECK( enumInfo.lookup(3) == "{** unexpected enum value **}" ) with expansion: {** unexpected enum value **} == @@ -4297,6 +4297,27 @@ with expansion: "this string contains 'abc' as a substring" ends with: "this" (case insensitive) +------------------------------------------------------------------------------- +Enum backed by larger underlying type +------------------------------------------------------------------------------- +EnumToString.tests.cpp: +............................................................................... + +EnumToString.tests.cpp:: PASSED: + REQUIRE( stringify( LargeEnum::Flag1 ) == "Flag1" ) +with expansion: + "Flag1" == "Flag1" + +EnumToString.tests.cpp:: PASSED: + REQUIRE( stringify( LargeEnum::Flag2 ) == "Flag2" ) +with expansion: + "Flag2" == "Flag2" + +EnumToString.tests.cpp:: PASSED: + REQUIRE( stringify( LargeEnum::Flag5 ) == "Flag5" ) +with expansion: + "Flag5" == "Flag5" + ------------------------------------------------------------------------------- Enums can quickly have stringification enabled using CATCH_REGISTER_ENUM ------------------------------------------------------------------------------- @@ -18372,10 +18393,10 @@ with expansion: parseEnums No enums ------------------------------------------------------------------------------- -ToString.tests.cpp: +EnumToString.tests.cpp: ............................................................................... -ToString.tests.cpp:: PASSED: +EnumToString.tests.cpp:: PASSED: CHECK_THAT( parseEnums( "" ), Equals( std::vector{} ) ) with expansion: { } Equals: { } @@ -18384,20 +18405,20 @@ with expansion: parseEnums One enum value ------------------------------------------------------------------------------- -ToString.tests.cpp: +EnumToString.tests.cpp: ............................................................................... -ToString.tests.cpp:: PASSED: +EnumToString.tests.cpp:: PASSED: CHECK_THAT( parseEnums( "ClassName::EnumName::Value1" ), Equals(std::vector{"Value1"} ) ) with expansion: { Value1 } Equals: { Value1 } -ToString.tests.cpp:: PASSED: +EnumToString.tests.cpp:: PASSED: CHECK_THAT( parseEnums( "Value1" ), Equals( std::vector{"Value1"} ) ) with expansion: { Value1 } Equals: { Value1 } -ToString.tests.cpp:: PASSED: +EnumToString.tests.cpp:: PASSED: CHECK_THAT( parseEnums( "EnumName::Value1" ), Equals(std::vector{"Value1"} ) ) with expansion: { Value1 } Equals: { Value1 } @@ -18406,20 +18427,20 @@ with expansion: parseEnums Multiple enum values ------------------------------------------------------------------------------- -ToString.tests.cpp: +EnumToString.tests.cpp: ............................................................................... -ToString.tests.cpp:: PASSED: +EnumToString.tests.cpp:: PASSED: CHECK_THAT( parseEnums( "ClassName::EnumName::Value1, ClassName::EnumName::Value2" ), Equals( std::vector{"Value1", "Value2"} ) ) with expansion: { Value1, Value2 } Equals: { Value1, Value2 } -ToString.tests.cpp:: PASSED: +EnumToString.tests.cpp:: PASSED: CHECK_THAT( parseEnums( "ClassName::EnumName::Value1, ClassName::EnumName::Value2, ClassName::EnumName::Value3" ), Equals( std::vector{"Value1", "Value2", "Value3"} ) ) with expansion: { Value1, Value2, Value3 } Equals: { Value1, Value2, Value3 } -ToString.tests.cpp:: PASSED: +EnumToString.tests.cpp:: PASSED: CHECK_THAT( parseEnums( "ClassName::EnumName::Value1,ClassName::EnumName::Value2 , ClassName::EnumName::Value3" ), Equals( std::vector{"Value1", "Value2", "Value3"} ) ) with expansion: { Value1, Value2, Value3 } Equals: { Value1, Value2, Value3 } @@ -20102,6 +20123,6 @@ Misc.tests.cpp: Misc.tests.cpp:: PASSED: =============================================================================== -test cases: 450 | 330 passed | 96 failed | 6 skipped | 18 failed as expected -assertions: 2413 | 2212 passed | 158 failed | 43 failed as expected +test cases: 451 | 331 passed | 96 failed | 6 skipped | 18 failed as expected +assertions: 2416 | 2215 passed | 158 failed | 43 failed as expected diff --git a/tests/SelfTest/Baselines/junit.sw.approved.txt b/tests/SelfTest/Baselines/junit.sw.approved.txt index f191b33f..328b466c 100644 --- a/tests/SelfTest/Baselines/junit.sw.approved.txt +++ b/tests/SelfTest/Baselines/junit.sw.approved.txt @@ -1,7 +1,7 @@ - + @@ -506,6 +506,7 @@ with expansion: at Matchers.tests.cpp: + diff --git a/tests/SelfTest/Baselines/junit.sw.multi.approved.txt b/tests/SelfTest/Baselines/junit.sw.multi.approved.txt index 3c152dc7..403ed251 100644 --- a/tests/SelfTest/Baselines/junit.sw.multi.approved.txt +++ b/tests/SelfTest/Baselines/junit.sw.multi.approved.txt @@ -1,6 +1,6 @@ - + @@ -505,6 +505,7 @@ with expansion: at Matchers.tests.cpp: + diff --git a/tests/SelfTest/Baselines/sonarqube.sw.approved.txt b/tests/SelfTest/Baselines/sonarqube.sw.approved.txt index fa472c71..f9e851fc 100644 --- a/tests/SelfTest/Baselines/sonarqube.sw.approved.txt +++ b/tests/SelfTest/Baselines/sonarqube.sw.approved.txt @@ -422,16 +422,11 @@ at AssertionHandler.tests.cpp: - - - - - @@ -1079,8 +1074,14 @@ at Decomposition.tests.cpp: + + + + + + diff --git a/tests/SelfTest/Baselines/sonarqube.sw.multi.approved.txt b/tests/SelfTest/Baselines/sonarqube.sw.multi.approved.txt index 3e970f26..e1ede12c 100644 --- a/tests/SelfTest/Baselines/sonarqube.sw.multi.approved.txt +++ b/tests/SelfTest/Baselines/sonarqube.sw.multi.approved.txt @@ -421,16 +421,11 @@ at AssertionHandler.tests.cpp: - - - - - @@ -1078,8 +1073,14 @@ at Decomposition.tests.cpp: + + + + + + diff --git a/tests/SelfTest/Baselines/tap.sw.approved.txt b/tests/SelfTest/Baselines/tap.sw.approved.txt index b6e218e3..7624d140 100644 --- a/tests/SelfTest/Baselines/tap.sw.approved.txt +++ b/tests/SelfTest/Baselines/tap.sw.approved.txt @@ -1053,11 +1053,11 @@ ok {test-number} - true with 1 message: 'a' # Delayed unscoped message clearing does not catch newly inserted messages not ok {test-number} - false with 1 message: 'b' # Directly creating an EnumInfo -ok {test-number} - enumInfo->lookup(0) == "Value1" for: Value1 == "Value1" +ok {test-number} - enumInfo.lookup(0) == "Value1" for: Value1 == "Value1" # Directly creating an EnumInfo -ok {test-number} - enumInfo->lookup(1) == "Value2" for: Value2 == "Value2" +ok {test-number} - enumInfo.lookup(1) == "Value2" for: Value2 == "Value2" # 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 @@ -1066,6 +1066,12 @@ ok {test-number} - Catch::makeStream( "" )->isConsole() for: true not ok {test-number} - testStringForMatching(), EndsWith( "Substring" ) for: "this string contains 'abc' as a substring" ends with: "Substring" # EndsWith string matcher not ok {test-number} - testStringForMatching(), EndsWith( "this", Catch::CaseSensitive::No ) for: "this string contains 'abc' as a substring" ends with: "this" (case insensitive) +# Enum backed by larger underlying type +ok {test-number} - stringify( LargeEnum::Flag1 ) == "Flag1" for: "Flag1" == "Flag1" +# Enum backed by larger underlying type +ok {test-number} - stringify( LargeEnum::Flag2 ) == "Flag2" for: "Flag2" == "Flag2" +# Enum backed by larger underlying type +ok {test-number} - stringify( LargeEnum::Flag5 ) == "Flag5" for: "Flag5" == "Flag5" # Enums can quickly have stringification enabled using CATCH_REGISTER_ENUM ok {test-number} - stringify( EnumClass3::Value1 ) == "Value1" for: "Value1" == "Value1" # Enums can quickly have stringification enabled using CATCH_REGISTER_ENUM @@ -4845,5 +4851,5 @@ ok {test-number} - q3 == 23. for: 23.0 == 23.0 ok {test-number} - # xmlentitycheck ok {test-number} - -1..2425 +1..2428 diff --git a/tests/SelfTest/Baselines/tap.sw.multi.approved.txt b/tests/SelfTest/Baselines/tap.sw.multi.approved.txt index 2defcecc..ed653421 100644 --- a/tests/SelfTest/Baselines/tap.sw.multi.approved.txt +++ b/tests/SelfTest/Baselines/tap.sw.multi.approved.txt @@ -1051,11 +1051,11 @@ ok {test-number} - true with 1 message: 'a' # Delayed unscoped message clearing does not catch newly inserted messages not ok {test-number} - false with 1 message: 'b' # Directly creating an EnumInfo -ok {test-number} - enumInfo->lookup(0) == "Value1" for: Value1 == "Value1" +ok {test-number} - enumInfo.lookup(0) == "Value1" for: Value1 == "Value1" # Directly creating an EnumInfo -ok {test-number} - enumInfo->lookup(1) == "Value2" for: Value2 == "Value2" +ok {test-number} - enumInfo.lookup(1) == "Value2" for: Value2 == "Value2" # 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 @@ -1064,6 +1064,12 @@ ok {test-number} - Catch::makeStream( "" )->isConsole() for: true not ok {test-number} - testStringForMatching(), EndsWith( "Substring" ) for: "this string contains 'abc' as a substring" ends with: "Substring" # EndsWith string matcher not ok {test-number} - testStringForMatching(), EndsWith( "this", Catch::CaseSensitive::No ) for: "this string contains 'abc' as a substring" ends with: "this" (case insensitive) +# Enum backed by larger underlying type +ok {test-number} - stringify( LargeEnum::Flag1 ) == "Flag1" for: "Flag1" == "Flag1" +# Enum backed by larger underlying type +ok {test-number} - stringify( LargeEnum::Flag2 ) == "Flag2" for: "Flag2" == "Flag2" +# Enum backed by larger underlying type +ok {test-number} - stringify( LargeEnum::Flag5 ) == "Flag5" for: "Flag5" == "Flag5" # Enums can quickly have stringification enabled using CATCH_REGISTER_ENUM ok {test-number} - stringify( EnumClass3::Value1 ) == "Value1" for: "Value1" == "Value1" # Enums can quickly have stringification enabled using CATCH_REGISTER_ENUM @@ -4834,5 +4840,5 @@ ok {test-number} - q3 == 23. for: 23.0 == 23.0 ok {test-number} - # xmlentitycheck ok {test-number} - -1..2425 +1..2428 diff --git a/tests/SelfTest/Baselines/teamcity.sw.approved.txt b/tests/SelfTest/Baselines/teamcity.sw.approved.txt index 57344d01..bbd587ff 100644 --- a/tests/SelfTest/Baselines/teamcity.sw.approved.txt +++ b/tests/SelfTest/Baselines/teamcity.sw.approved.txt @@ -338,6 +338,8 @@ ##teamcity[testFailed name='EndsWith string matcher' message='Matchers.tests.cpp:|n...............................................................................|n|nMatchers.tests.cpp:|nexpression failed|n CHECK_THAT( testStringForMatching(), EndsWith( "Substring" ) )|nwith expansion:|n "this string contains |'abc|' as a substring" ends with: "Substring"|n'] ##teamcity[testFailed name='EndsWith string matcher' message='Matchers.tests.cpp:|nexpression failed|n CHECK_THAT( testStringForMatching(), EndsWith( "this", Catch::CaseSensitive::No ) )|nwith expansion:|n "this string contains |'abc|' as a substring" ends with: "this" (case insensitive)|n'] ##teamcity[testFinished name='EndsWith string matcher' duration="{duration}"] +##teamcity[testStarted name='Enum backed by larger underlying type'] +##teamcity[testFinished name='Enum backed by larger underlying type' duration="{duration}"] ##teamcity[testStarted name='Enums can quickly have stringification enabled using CATCH_REGISTER_ENUM'] ##teamcity[testFinished name='Enums can quickly have stringification enabled using CATCH_REGISTER_ENUM' duration="{duration}"] ##teamcity[testStarted name='Enums in namespaces can quickly have stringification enabled using CATCH_REGISTER_ENUM'] diff --git a/tests/SelfTest/Baselines/teamcity.sw.multi.approved.txt b/tests/SelfTest/Baselines/teamcity.sw.multi.approved.txt index 9634d705..fb73387f 100644 --- a/tests/SelfTest/Baselines/teamcity.sw.multi.approved.txt +++ b/tests/SelfTest/Baselines/teamcity.sw.multi.approved.txt @@ -338,6 +338,8 @@ ##teamcity[testFailed name='EndsWith string matcher' message='Matchers.tests.cpp:|n...............................................................................|n|nMatchers.tests.cpp:|nexpression failed|n CHECK_THAT( testStringForMatching(), EndsWith( "Substring" ) )|nwith expansion:|n "this string contains |'abc|' as a substring" ends with: "Substring"|n'] ##teamcity[testFailed name='EndsWith string matcher' message='Matchers.tests.cpp:|nexpression failed|n CHECK_THAT( testStringForMatching(), EndsWith( "this", Catch::CaseSensitive::No ) )|nwith expansion:|n "this string contains |'abc|' as a substring" ends with: "this" (case insensitive)|n'] ##teamcity[testFinished name='EndsWith string matcher' duration="{duration}"] +##teamcity[testStarted name='Enum backed by larger underlying type'] +##teamcity[testFinished name='Enum backed by larger underlying type' duration="{duration}"] ##teamcity[testStarted name='Enums can quickly have stringification enabled using CATCH_REGISTER_ENUM'] ##teamcity[testFinished name='Enums can quickly have stringification enabled using CATCH_REGISTER_ENUM' duration="{duration}"] ##teamcity[testStarted name='Enums in namespaces can quickly have stringification enabled using CATCH_REGISTER_ENUM'] diff --git a/tests/SelfTest/Baselines/xml.sw.approved.txt b/tests/SelfTest/Baselines/xml.sw.approved.txt index ed263d43..933094d3 100644 --- a/tests/SelfTest/Baselines/xml.sw.approved.txt +++ b/tests/SelfTest/Baselines/xml.sw.approved.txt @@ -4743,26 +4743,26 @@ C - - + + - enumInfo->lookup(0) == "Value1" + enumInfo.lookup(0) == "Value1" Value1 == "Value1" - + - enumInfo->lookup(1) == "Value2" + enumInfo.lookup(1) == "Value2" Value2 == "Value2" - + - enumInfo->lookup(3) == "{** unexpected enum value **}" + enumInfo.lookup(3) == "{** unexpected enum value **}" {** unexpected enum value **} @@ -4808,6 +4808,33 @@ C + + + + stringify( LargeEnum::Flag1 ) == "Flag1" + + + "Flag1" == "Flag1" + + + + + stringify( LargeEnum::Flag2 ) == "Flag2" + + + "Flag2" == "Flag2" + + + + + stringify( LargeEnum::Flag5 ) == "Flag5" + + + "Flag5" == "Flag5" + + + + @@ -21361,9 +21388,9 @@ Approx( -1.95996398454005449 ) - -
- + +
+ parseEnums( "" ), Equals( std::vector<Catch::StringRef>{} ) @@ -21373,8 +21400,8 @@ Approx( -1.95996398454005449 )
-
- +
+ parseEnums( "ClassName::EnumName::Value1" ), Equals(std::vector<Catch::StringRef>{"Value1"} ) @@ -21382,7 +21409,7 @@ Approx( -1.95996398454005449 ) { Value1 } Equals: { Value1 } - + parseEnums( "Value1" ), Equals( std::vector<Catch::StringRef>{"Value1"} ) @@ -21390,7 +21417,7 @@ Approx( -1.95996398454005449 ) { Value1 } Equals: { Value1 } - + parseEnums( "EnumName::Value1" ), Equals(std::vector<Catch::StringRef>{"Value1"} ) @@ -21400,8 +21427,8 @@ Approx( -1.95996398454005449 )
-
- +
+ parseEnums( "ClassName::EnumName::Value1, ClassName::EnumName::Value2" ), Equals( std::vector<Catch::StringRef>{"Value1", "Value2"} ) @@ -21409,7 +21436,7 @@ Approx( -1.95996398454005449 ) { Value1, Value2 } Equals: { Value1, Value2 } - + parseEnums( "ClassName::EnumName::Value1, ClassName::EnumName::Value2, ClassName::EnumName::Value3" ), Equals( std::vector<Catch::StringRef>{"Value1", "Value2", "Value3"} ) @@ -21417,7 +21444,7 @@ Approx( -1.95996398454005449 ) { Value1, Value2, Value3 } Equals: { Value1, Value2, Value3 } - + parseEnums( "ClassName::EnumName::Value1,ClassName::EnumName::Value2 , ClassName::EnumName::Value3" ), Equals( std::vector<Catch::StringRef>{"Value1", "Value2", "Value3"} ) @@ -23358,6 +23385,6 @@ Approx( -1.95996398454005449 )
- - + + diff --git a/tests/SelfTest/Baselines/xml.sw.multi.approved.txt b/tests/SelfTest/Baselines/xml.sw.multi.approved.txt index ea955701..646f0c72 100644 --- a/tests/SelfTest/Baselines/xml.sw.multi.approved.txt +++ b/tests/SelfTest/Baselines/xml.sw.multi.approved.txt @@ -4743,26 +4743,26 @@ C
- - + + - enumInfo->lookup(0) == "Value1" + enumInfo.lookup(0) == "Value1" Value1 == "Value1" - + - enumInfo->lookup(1) == "Value2" + enumInfo.lookup(1) == "Value2" Value2 == "Value2" - + - enumInfo->lookup(3) == "{** unexpected enum value **}" + enumInfo.lookup(3) == "{** unexpected enum value **}" {** unexpected enum value **} @@ -4808,6 +4808,33 @@ C + + + + stringify( LargeEnum::Flag1 ) == "Flag1" + + + "Flag1" == "Flag1" + + + + + stringify( LargeEnum::Flag2 ) == "Flag2" + + + "Flag2" == "Flag2" + + + + + stringify( LargeEnum::Flag5 ) == "Flag5" + + + "Flag5" == "Flag5" + + + + @@ -21360,9 +21387,9 @@ Approx( -1.95996398454005449 ) - -
- + +
+ parseEnums( "" ), Equals( std::vector<Catch::StringRef>{} ) @@ -21372,8 +21399,8 @@ Approx( -1.95996398454005449 )
-
- +
+ parseEnums( "ClassName::EnumName::Value1" ), Equals(std::vector<Catch::StringRef>{"Value1"} ) @@ -21381,7 +21408,7 @@ Approx( -1.95996398454005449 ) { Value1 } Equals: { Value1 } - + parseEnums( "Value1" ), Equals( std::vector<Catch::StringRef>{"Value1"} ) @@ -21389,7 +21416,7 @@ Approx( -1.95996398454005449 ) { Value1 } Equals: { Value1 } - + parseEnums( "EnumName::Value1" ), Equals(std::vector<Catch::StringRef>{"Value1"} ) @@ -21399,8 +21426,8 @@ Approx( -1.95996398454005449 )
-
- +
+ parseEnums( "ClassName::EnumName::Value1, ClassName::EnumName::Value2" ), Equals( std::vector<Catch::StringRef>{"Value1", "Value2"} ) @@ -21408,7 +21435,7 @@ Approx( -1.95996398454005449 ) { Value1, Value2 } Equals: { Value1, Value2 } - + parseEnums( "ClassName::EnumName::Value1, ClassName::EnumName::Value2, ClassName::EnumName::Value3" ), Equals( std::vector<Catch::StringRef>{"Value1", "Value2", "Value3"} ) @@ -21416,7 +21443,7 @@ Approx( -1.95996398454005449 ) { Value1, Value2, Value3 } Equals: { Value1, Value2, Value3 } - + parseEnums( "ClassName::EnumName::Value1,ClassName::EnumName::Value2 , ClassName::EnumName::Value3" ), Equals( std::vector<Catch::StringRef>{"Value1", "Value2", "Value3"} ) @@ -23357,6 +23384,6 @@ Approx( -1.95996398454005449 )
- - + + diff --git a/tests/SelfTest/IntrospectiveTests/Reporters.tests.cpp b/tests/SelfTest/IntrospectiveTests/Reporters.tests.cpp index edf7f3fd..afb5143a 100644 --- a/tests/SelfTest/IntrospectiveTests/Reporters.tests.cpp +++ b/tests/SelfTest/IntrospectiveTests/Reporters.tests.cpp @@ -12,6 +12,7 @@ #include #include #include +#include #include #include #include diff --git a/tests/SelfTest/IntrospectiveTests/ToString.tests.cpp b/tests/SelfTest/IntrospectiveTests/ToString.tests.cpp index 01d989a7..780c951c 100644 --- a/tests/SelfTest/IntrospectiveTests/ToString.tests.cpp +++ b/tests/SelfTest/IntrospectiveTests/ToString.tests.cpp @@ -10,14 +10,10 @@ #include #include #include -#include #include -#include #include -enum class EnumClass3 { Value1, Value2, Value3, Value4 }; - struct UsesSentinel { using const_iterator = int const*; using const_sentinel = std::nullptr_t; @@ -26,42 +22,6 @@ struct UsesSentinel { const_iterator end() const { return nullptr; } }; -TEST_CASE( "parseEnums", "[Strings][enums]" ) { - using namespace Catch::Matchers; - using Catch::Detail::parseEnums; - - SECTION( "No enums" ) - CHECK_THAT( parseEnums( "" ), Equals( std::vector{} ) ); - - SECTION( "One enum value" ) { - CHECK_THAT( parseEnums( "ClassName::EnumName::Value1" ), - Equals(std::vector{"Value1"} ) ); - CHECK_THAT( parseEnums( "Value1" ), - Equals( std::vector{"Value1"} ) ); - CHECK_THAT( parseEnums( "EnumName::Value1" ), - Equals(std::vector{"Value1"} ) ); - } - - SECTION( "Multiple enum values" ) { - CHECK_THAT( parseEnums( "ClassName::EnumName::Value1, ClassName::EnumName::Value2" ), - Equals( std::vector{"Value1", "Value2"} ) ); - CHECK_THAT( parseEnums( "ClassName::EnumName::Value1, ClassName::EnumName::Value2, ClassName::EnumName::Value3" ), - Equals( std::vector{"Value1", "Value2", "Value3"} ) ); - CHECK_THAT( parseEnums( "ClassName::EnumName::Value1,ClassName::EnumName::Value2 , ClassName::EnumName::Value3" ), - Equals( std::vector{"Value1", "Value2", "Value3"} ) ); - } -} - -TEST_CASE( "Directly creating an EnumInfo" ) { - - using namespace Catch::Detail; - auto enumInfo = makeEnumInfo( "EnumName", "EnumName::Value1, EnumName::Value2", {0, 1} ); - - CHECK( enumInfo->lookup(0) == "Value1" ); - CHECK( enumInfo->lookup(1) == "Value2" ); - CHECK( enumInfo->lookup(3) == "{** unexpected enum value **}" ); -} - TEST_CASE("Range type with sentinel") { CHECK( Catch::Detail::stringify(UsesSentinel{}) == "{ }" ); } diff --git a/tests/SelfTest/UsageTests/EnumToString.tests.cpp b/tests/SelfTest/UsageTests/EnumToString.tests.cpp index 268a7cad..bacd5608 100644 --- a/tests/SelfTest/UsageTests/EnumToString.tests.cpp +++ b/tests/SelfTest/UsageTests/EnumToString.tests.cpp @@ -7,8 +7,60 @@ // SPDX-License-Identifier: BSL-1.0 #include -#include +#include +#include +namespace Bikeshed { + enum class Colours { Red, Green, Blue }; +} + +// Important!: This macro must appear at top level scope - not inside a namespace +// You can fully qualify the names, or use a using if you prefer +CATCH_REGISTER_ENUM( Bikeshed::Colours, + Bikeshed::Colours::Red, + Bikeshed::Colours::Green, + Bikeshed::Colours::Blue ) + +TEST_CASE( "Enums in namespaces can quickly have stringification enabled using CATCH_REGISTER_ENUM" ) { + using Catch::Detail::stringify; + REQUIRE( stringify( Bikeshed::Colours::Red ) == "Red" ); + REQUIRE( stringify( Bikeshed::Colours::Blue ) == "Blue" ); +} + +TEST_CASE( "parseEnums", "[Strings][enums]" ) { + using namespace Catch::Matchers; + using Catch::Detail::parseEnums; + + SECTION( "No enums" ) + CHECK_THAT( parseEnums( "" ), Equals( std::vector{} ) ); + + SECTION( "One enum value" ) { + CHECK_THAT( parseEnums( "ClassName::EnumName::Value1" ), + Equals(std::vector{"Value1"} ) ); + CHECK_THAT( parseEnums( "Value1" ), + Equals( std::vector{"Value1"} ) ); + CHECK_THAT( parseEnums( "EnumName::Value1" ), + Equals(std::vector{"Value1"} ) ); + } + + SECTION( "Multiple enum values" ) { + CHECK_THAT( parseEnums( "ClassName::EnumName::Value1, ClassName::EnumName::Value2" ), + Equals( std::vector{"Value1", "Value2"} ) ); + CHECK_THAT( parseEnums( "ClassName::EnumName::Value1, ClassName::EnumName::Value2, ClassName::EnumName::Value3" ), + Equals( std::vector{"Value1", "Value2", "Value3"} ) ); + CHECK_THAT( parseEnums( "ClassName::EnumName::Value1,ClassName::EnumName::Value2 , ClassName::EnumName::Value3" ), + Equals( std::vector{"Value1", "Value2", "Value3"} ) ); + } +} + +TEST_CASE( "Directly creating an EnumInfo" ) { + using namespace Catch::Detail; + auto enumInfo = makeEnumInfo( "EnumName", "EnumName::Value1, EnumName::Value2", {0, 1} ); + + CHECK( enumInfo.lookup(0) == "Value1" ); + CHECK( enumInfo.lookup(1) == "Value2" ); + CHECK( enumInfo.lookup(3) == "{** unexpected enum value **}" ); +} namespace { // Enum without user-provided stream operator @@ -90,19 +142,24 @@ TEST_CASE( "Enums can quickly have stringification enabled using CATCH_REGISTER_ REQUIRE( stringify( ec3 ) == "Value2" ); } -namespace Bikeshed { - enum class Colours { Red, Green, Blue }; -} +enum class LargeEnum : std::int64_t { + Flag1 = 0x01, + Flag2 = 0x02, + Flag3 = 0x04, + Flag4 = 0x08, + Flag5 = 0x10, +}; -// Important!: This macro must appear at top level scope - not inside a namespace -// You can fully qualify the names, or use a using if you prefer -CATCH_REGISTER_ENUM( Bikeshed::Colours, - Bikeshed::Colours::Red, - Bikeshed::Colours::Green, - Bikeshed::Colours::Blue ) +CATCH_REGISTER_ENUM( LargeEnum, + LargeEnum::Flag1, + LargeEnum::Flag2, + LargeEnum::Flag3, + LargeEnum::Flag4, + LargeEnum::Flag5 ) -TEST_CASE( "Enums in namespaces can quickly have stringification enabled using CATCH_REGISTER_ENUM" ) { +TEST_CASE( "Enum backed by larger underlying type", "[enum][toString]" ) { using Catch::Detail::stringify; - REQUIRE( stringify( Bikeshed::Colours::Red ) == "Red" ); - REQUIRE( stringify( Bikeshed::Colours::Blue ) == "Blue" ); + REQUIRE( stringify( LargeEnum::Flag1 ) == "Flag1" ); + REQUIRE( stringify( LargeEnum::Flag2 ) == "Flag2" ); + REQUIRE( stringify( LargeEnum::Flag5 ) == "Flag5" ); }