First commit of STRINGIFY_ENUM

This commit is contained in:
Phil nash 2019-04-04 15:55:46 +01:00
parent 08147a23f9
commit 43428c6093
16 changed files with 587 additions and 8 deletions

View File

@ -0,0 +1,68 @@
/*
* Created by Phil on 4/4/2019.
* Copyright 2019 Two Blue Cubes Ltd. All rights reserved.
*
* Distributed under the Boost Software License, Version 1.0. (See accompanying
* file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
*/
#include "catch_enum_values_registry.h"
#include "catch_string_manip.h"
#include "catch_stream.h"
#include <map>
namespace Catch {
IMutableEnumValuesRegistry::~IMutableEnumValuesRegistry() {}
IEnumInfo::~IEnumInfo() {}
namespace Detail {
std::vector<std::string> parseEnums( StringRef enums ) {
auto enumValues = splitString( enums, ',' );
std::vector<std::string> parsed;
parsed.reserve( enumValues.size() );
for( auto const& enumValue : enumValues ) {
auto identifiers = splitString( enumValue, ':' );
parsed.push_back( Catch::trim( identifiers.back() ) );
}
return parsed;
}
struct EnumInfo : IEnumInfo {
std::string m_name;
std::map<int, std::string> m_values;
~EnumInfo();
std::string lookup( int value ) const override {
auto it = m_values.find( value );
if( it == m_values.end() ) {
ReusableStringStream rss;
rss << "{** unexpected value for " << m_name << ": " << value << "**}";
return rss.str();
}
return it->second;
}
};
EnumInfo::~EnumInfo() {}
IEnumInfo const& EnumValuesRegistry::registerEnum( StringRef enumName, StringRef allValueNames, std::vector<int> const& values ) {
std::unique_ptr<EnumInfo> enumInfo( new EnumInfo );
enumInfo->m_name = enumName;
const auto valueNames = Catch::Detail::parseEnums( allValueNames );
assert( valueNames.size() == values.size() );
std::size_t i = 0;
for( auto value : values )
enumInfo->m_values.insert({ value, valueNames[i++] });
EnumInfo* raw = enumInfo.get();
m_enumInfos.push_back( std::move( enumInfo ) );
return *raw;
}
} // Detail
} // Catch

View File

@ -0,0 +1,32 @@
/*
* Created by Phil on 4/4/2019.
* Copyright 2019 Two Blue Cubes Ltd. All rights reserved.
*
* Distributed under the Boost Software License, Version 1.0. (See accompanying
* file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
*/
#ifndef TWOBLUECUBES_CATCH_ENUMVALUESREGISTRY_H_INCLUDED
#define TWOBLUECUBES_CATCH_ENUMVALUESREGISTRY_H_INCLUDED
#include "catch_interfaces_enum_values_registry.h"
#include <vector>
namespace Catch {
namespace Detail {
class EnumValuesRegistry : public IMutableEnumValuesRegistry {
std::vector<std::unique_ptr<IEnumInfo>> m_enumInfos;
IEnumInfo const& registerEnum(StringRef enumName, StringRef allEnums, std::vector<int> const& values) override;
};
std::vector<std::string> parseEnums( StringRef enums );
} // Detail
} // Catch
#endif //TWOBLUECUBES_CATCH_ENUMVALUESREGISTRY_H_INCLUDED

View File

@ -0,0 +1,40 @@
/*
* Created by Phil on 4/4/2019.
* Copyright 2019 Two Blue Cubes Ltd. All rights reserved.
*
* Distributed under the Boost Software License, Version 1.0. (See accompanying
* file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
*/
#ifndef TWOBLUECUBES_CATCH_INTERFACESENUMVALUESREGISTRY_H_INCLUDED
#define TWOBLUECUBES_CATCH_INTERFACESENUMVALUESREGISTRY_H_INCLUDED
#include "catch_stringref.h"
#include <vector>
namespace Catch {
struct IEnumInfo {
virtual ~IEnumInfo();
virtual std::string lookup( int value ) const = 0;
};
struct IMutableEnumValuesRegistry {
virtual ~IMutableEnumValuesRegistry();
virtual IEnumInfo const& registerEnum( StringRef enumName, StringRef allEnums, std::vector<int> const& values ) = 0;
template<typename E>
IEnumInfo const& registerEnum( StringRef enumName, StringRef allEnums, std::initializer_list<E> values ) {
std::vector<int> intValues;
intValues.reserve( values.size() );
for( auto enumValue : values )
intValues.push_back( static_cast<int>( enumValue ) );
return registerEnum( enumName, allEnums, intValues );
}
};
} // Catch
#endif //TWOBLUECUBES_CATCH_INTERFACESENUMVALUESREGISTRY_H_INCLUDED

View File

@ -22,6 +22,8 @@ namespace Catch {
struct IReporterRegistry; struct IReporterRegistry;
struct IReporterFactory; struct IReporterFactory;
struct ITagAliasRegistry; struct ITagAliasRegistry;
struct IMutableEnumValuesRegistry;
class StartupExceptionRegistry; class StartupExceptionRegistry;
using IReporterFactoryPtr = std::shared_ptr<IReporterFactory>; using IReporterFactoryPtr = std::shared_ptr<IReporterFactory>;
@ -32,7 +34,6 @@ namespace Catch {
virtual IReporterRegistry const& getReporterRegistry() const = 0; virtual IReporterRegistry const& getReporterRegistry() const = 0;
virtual ITestCaseRegistry const& getTestCaseRegistry() const = 0; virtual ITestCaseRegistry const& getTestCaseRegistry() const = 0;
virtual ITagAliasRegistry const& getTagAliasRegistry() const = 0; virtual ITagAliasRegistry const& getTagAliasRegistry() const = 0;
virtual IExceptionTranslatorRegistry const& getExceptionTranslatorRegistry() const = 0; virtual IExceptionTranslatorRegistry const& getExceptionTranslatorRegistry() const = 0;
@ -47,6 +48,7 @@ namespace Catch {
virtual void registerTranslator( const IExceptionTranslator* translator ) = 0; virtual void registerTranslator( const IExceptionTranslator* translator ) = 0;
virtual void registerTagAlias( std::string const& alias, std::string const& tag, SourceLineInfo const& lineInfo ) = 0; virtual void registerTagAlias( std::string const& alias, std::string const& tag, SourceLineInfo const& lineInfo ) = 0;
virtual void registerStartupException() noexcept = 0; virtual void registerStartupException() noexcept = 0;
virtual IMutableEnumValuesRegistry& getMutableEnumValuesRegistry() = 0;
}; };
IRegistryHub const& getRegistryHub(); IRegistryHub const& getRegistryHub();

View File

@ -15,6 +15,7 @@
#include "catch_tag_alias_registry.h" #include "catch_tag_alias_registry.h"
#include "catch_startup_exception_registry.h" #include "catch_startup_exception_registry.h"
#include "catch_singletons.hpp" #include "catch_singletons.hpp"
#include "catch_enum_values_registry.h"
namespace Catch { namespace Catch {
@ -60,6 +61,9 @@ namespace Catch {
void registerStartupException() noexcept override { void registerStartupException() noexcept override {
m_exceptionRegistry.add(std::current_exception()); m_exceptionRegistry.add(std::current_exception());
} }
IMutableEnumValuesRegistry& getMutableEnumValuesRegistry() override {
return m_enumValuesRegistry;
}
private: private:
TestRegistry m_testCaseRegistry; TestRegistry m_testCaseRegistry;
@ -67,6 +71,7 @@ namespace Catch {
ExceptionTranslatorRegistry m_exceptionTranslatorRegistry; ExceptionTranslatorRegistry m_exceptionTranslatorRegistry;
TagAliasRegistry m_tagAliasRegistry; TagAliasRegistry m_tagAliasRegistry;
StartupExceptionRegistry m_exceptionRegistry; StartupExceptionRegistry m_exceptionRegistry;
Detail::EnumValuesRegistry m_enumValuesRegistry;
}; };
} }

View File

@ -6,11 +6,13 @@
*/ */
#include "catch_string_manip.h" #include "catch_string_manip.h"
#include "catch_stringref.h"
#include <algorithm> #include <algorithm>
#include <ostream> #include <ostream>
#include <cstring> #include <cstring>
#include <cctype> #include <cctype>
#include <vector>
namespace Catch { namespace Catch {
@ -65,6 +67,21 @@ namespace Catch {
return replaced; return replaced;
} }
std::vector<std::string> splitString( StringRef str, char delimiter ) {
std::vector<std::string> subStrings;
std::size_t start = 0;
for(std::size_t pos = 0; pos < str.size(); ++pos ) {
if( str[pos] == delimiter ) {
if( pos - start > 1 )
subStrings.push_back( str.substr( start, pos-start ) );
start = pos+1;
}
}
if( start < str.size() )
subStrings.push_back( str.substr( start, str.size()-start ) );
return subStrings;
}
pluralise::pluralise( std::size_t count, std::string const& label ) pluralise::pluralise( std::size_t count, std::string const& label )
: m_count( count ), : m_count( count ),
m_label( label ) m_label( label )

View File

@ -12,6 +12,8 @@
namespace Catch { namespace Catch {
class StringRef;
bool startsWith( std::string const& s, std::string const& prefix ); bool startsWith( std::string const& s, std::string const& prefix );
bool startsWith( std::string const& s, char prefix ); bool startsWith( std::string const& s, char prefix );
bool endsWith( std::string const& s, std::string const& suffix ); bool endsWith( std::string const& s, std::string const& suffix );
@ -21,6 +23,7 @@ namespace Catch {
std::string toLower( std::string const& s ); std::string toLower( std::string const& s );
std::string trim( std::string const& str ); std::string trim( std::string const& str );
bool replaceInPlace( std::string& str, std::string const& replaceThis, std::string const& withThis ); bool replaceInPlace( std::string& str, std::string const& replaceThis, std::string const& withThis );
std::vector<std::string> splitString( StringRef str, char delimiter );
struct pluralise { struct pluralise {
pluralise( std::size_t count, std::string const& label ); pluralise( std::size_t count, std::string const& label );

View File

@ -15,6 +15,7 @@
#include <string> #include <string>
#include "catch_compiler_capabilities.h" #include "catch_compiler_capabilities.h"
#include "catch_stream.h" #include "catch_stream.h"
#include "catch_interfaces_enum_values_registry.h"
#ifdef CATCH_CONFIG_CPP17_STRING_VIEW #ifdef CATCH_CONFIG_CPP17_STRING_VIEW
#include <string_view> #include <string_view>
@ -639,6 +640,19 @@ struct ratio_string<std::milli> {
} }
#endif // CATCH_CONFIG_ENABLE_CHRONO_STRINGMAKER #endif // CATCH_CONFIG_ENABLE_CHRONO_STRINGMAKER
#define INTERNAL_CATCH_STRINGIFY_ENUM( enumName, ... ) \
template<> struct ::Catch::StringMaker<enumName> { \
static std::string convert( enumName value ) { \
static const auto& enumInfo = ::Catch::getMutableRegistryHub().getMutableEnumValuesRegistry().registerEnum( #enumName, #__VA_ARGS__, { __VA_ARGS__ } ); \
return enumInfo.lookup( static_cast<int>( value ) ); \
} \
};
#ifdef CATCH_CONFIG_PREFIX_ALL
# define CATCH_STRINGIFY_ENUM( enumName, ... ) INTERNAL_CATCH_STRINGIFY_ENUM( enumName, __VA_ARGS__ )
#else
# define STRINGIFY_ENUM( enumName, ... ) INTERNAL_CATCH_STRINGIFY_ENUM( enumName, __VA_ARGS__ )
#endif
#ifdef _MSC_VER #ifdef _MSC_VER
#pragma warning(pop) #pragma warning(pop)

View File

@ -97,6 +97,7 @@ set(INTERNAL_HEADERS
${HEADER_DIR}/internal/catch_decomposer.h ${HEADER_DIR}/internal/catch_decomposer.h
${HEADER_DIR}/internal/catch_default_main.hpp ${HEADER_DIR}/internal/catch_default_main.hpp
${HEADER_DIR}/internal/catch_enforce.h ${HEADER_DIR}/internal/catch_enforce.h
${HEADER_DIR}/internal/catch_enum_values_registry.h
${HEADER_DIR}/internal/catch_errno_guard.h ${HEADER_DIR}/internal/catch_errno_guard.h
${HEADER_DIR}/internal/catch_exception_translator_registry.h ${HEADER_DIR}/internal/catch_exception_translator_registry.h
${HEADER_DIR}/internal/catch_external_interfaces.h ${HEADER_DIR}/internal/catch_external_interfaces.h
@ -107,6 +108,7 @@ set(INTERNAL_HEADERS
${HEADER_DIR}/internal/catch_impl.hpp ${HEADER_DIR}/internal/catch_impl.hpp
${HEADER_DIR}/internal/catch_interfaces_capture.h ${HEADER_DIR}/internal/catch_interfaces_capture.h
${HEADER_DIR}/internal/catch_interfaces_config.h ${HEADER_DIR}/internal/catch_interfaces_config.h
${HEADER_DIR}/internal/catch_interfaces_enum_values_registry.h
${HEADER_DIR}/internal/catch_interfaces_exception.h ${HEADER_DIR}/internal/catch_interfaces_exception.h
${HEADER_DIR}/internal/catch_interfaces_registry_hub.h ${HEADER_DIR}/internal/catch_interfaces_registry_hub.h
${HEADER_DIR}/internal/catch_interfaces_reporter.h ${HEADER_DIR}/internal/catch_interfaces_reporter.h
@ -182,6 +184,7 @@ set(IMPL_SOURCES
${HEADER_DIR}/internal/catch_debugger.cpp ${HEADER_DIR}/internal/catch_debugger.cpp
${HEADER_DIR}/internal/catch_decomposer.cpp ${HEADER_DIR}/internal/catch_decomposer.cpp
${HEADER_DIR}/internal/catch_enforce.cpp ${HEADER_DIR}/internal/catch_enforce.cpp
${HEADER_DIR}/internal/catch_enum_values_registry.cpp
${HEADER_DIR}/internal/catch_errno_guard.cpp ${HEADER_DIR}/internal/catch_errno_guard.cpp
${HEADER_DIR}/internal/catch_exception_translator_registry.cpp ${HEADER_DIR}/internal/catch_exception_translator_registry.cpp
${HEADER_DIR}/internal/catch_fatal_condition.cpp ${HEADER_DIR}/internal/catch_fatal_condition.cpp

View File

@ -298,6 +298,11 @@ Approx.tests.cpp:<line number>: passed: 101.000001 != Approx(100).epsilon(0.01)
Approx.tests.cpp:<line number>: passed: std::pow(10, -5) != Approx(std::pow(10, -7)) for: 0.00001 != Approx( 0.0000001 ) Approx.tests.cpp:<line number>: passed: std::pow(10, -5) != Approx(std::pow(10, -7)) for: 0.00001 != Approx( 0.0000001 )
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)
EnumToString.tests.cpp:<line number>: passed: enumInfo.lookup(0) == "Value1" for: "Value1" == "Value1"
EnumToString.tests.cpp:<line number>: passed: enumInfo.lookup(1) == "Value2" for: "Value2" == "Value2"
EnumToString.tests.cpp:<line number>: passed: enumInfo.lookup(3) == "{** unexpected value for EnumName: 3**}" for: "{** unexpected value for EnumName: 3**}"
==
"{** unexpected value for EnumName: 3**}"
Approx.tests.cpp:<line number>: passed: 101.01 != Approx(100).epsilon(0.01) for: 101.01 != Approx( 100.0 ) Approx.tests.cpp:<line number>: passed: 101.01 != Approx(100).epsilon(0.01) for: 101.01 != Approx( 100.0 )
Condition.tests.cpp:<line number>: failed: data.int_seven == 6 for: 7 == 6 Condition.tests.cpp:<line number>: failed: data.int_seven == 6 for: 7 == 6
Condition.tests.cpp:<line number>: failed: data.int_seven == 8 for: 7 == 8 Condition.tests.cpp:<line number>: failed: data.int_seven == 8 for: 7 == 8
@ -912,6 +917,13 @@ Matchers.tests.cpp:<line number>: failed: testStringForMatching(), Matches("this
Matchers.tests.cpp:<line number>: failed: testStringForMatching(), Matches("contains 'abc' as a substring") for: "this string contains 'abc' as a substring" matches "contains 'abc' as a substring" case sensitively Matchers.tests.cpp:<line number>: failed: testStringForMatching(), Matches("contains 'abc' as a substring") for: "this string contains 'abc' as a substring" matches "contains 'abc' as a substring" case sensitively
Matchers.tests.cpp:<line number>: failed: testStringForMatching(), Matches("this string contains 'abc' as a") for: "this string contains 'abc' as a substring" matches "this string contains 'abc' as a" case sensitively Matchers.tests.cpp:<line number>: failed: testStringForMatching(), Matches("this string contains 'abc' as a") for: "this string contains 'abc' as a substring" matches "this string contains 'abc' as a" case sensitively
Matchers.tests.cpp:<line number>: passed: actual, !UnorderedEquals(expected) for: { 'a', 'b' } not UnorderedEquals: { 'c', 'b' } Matchers.tests.cpp:<line number>: passed: actual, !UnorderedEquals(expected) for: { 'a', 'b' } not UnorderedEquals: { 'c', 'b' }
EnumToString.tests.cpp:<line number>: passed: stringify( EnumClass3::Value1 ) == "Value1" for: "Value1" == "Value1"
EnumToString.tests.cpp:<line number>: passed: stringify( EnumClass3::Value2 ) == "Value2" for: "Value2" == "Value2"
EnumToString.tests.cpp:<line number>: passed: stringify( EnumClass3::Value3 ) == "Value3" for: "Value3" == "Value3"
EnumToString.tests.cpp:<line number>: passed: stringify( EnumClass3::Value4 ) == "{** unexpected value for EnumClass3: 3**}" for: "{** unexpected value for EnumClass3: 3**}"
==
"{** unexpected value for EnumClass3: 3**}"
EnumToString.tests.cpp:<line number>: passed: stringify( ec3 ) == "Value2" for: "Value2" == "Value2"
Message.tests.cpp:<line number>: passed: with 1 message: 'this is a success' Message.tests.cpp:<line number>: passed: with 1 message: 'this is a success'
Message.tests.cpp:<line number>: passed: Message.tests.cpp:<line number>: passed:
BDD.tests.cpp:<line number>: passed: before == 0 for: 0 == 0 BDD.tests.cpp:<line number>: passed: before == 0 for: 0 == 0
@ -1352,6 +1364,13 @@ Tricky.tests.cpp:<line number>: passed: ptr.get() == 0 for: 0 == 0
ToStringPair.tests.cpp:<line number>: passed: ::Catch::Detail::stringify( pair ) == "{ { 42, \"Arthur\" }, { \"Ford\", 24 } }" for: "{ { 42, "Arthur" }, { "Ford", 24 } }" ToStringPair.tests.cpp:<line number>: passed: ::Catch::Detail::stringify( pair ) == "{ { 42, \"Arthur\" }, { \"Ford\", 24 } }" for: "{ { 42, "Arthur" }, { "Ford", 24 } }"
== ==
"{ { 42, "Arthur" }, { "Ford", 24 } }" "{ { 42, "Arthur" }, { "Ford", 24 } }"
EnumToString.tests.cpp:<line number>: passed: parseEnums( "" ), Equals( std::vector<std::string>{} ) for: { } Equals: { }
EnumToString.tests.cpp:<line number>: passed: parseEnums( "ClassName::EnumName::Value1" ), Equals(std::vector<std::string>{"Value1"} ) for: { "Value1" } Equals: { "Value1" }
EnumToString.tests.cpp:<line number>: passed: parseEnums( "Value1" ), Equals( std::vector<std::string>{"Value1"} ) for: { "Value1" } Equals: { "Value1" }
EnumToString.tests.cpp:<line number>: passed: parseEnums( "EnumName::Value1" ), Equals(std::vector<std::string>{"Value1"} ) for: { "Value1" } Equals: { "Value1" }
EnumToString.tests.cpp:<line number>: passed: parseEnums( "ClassName::EnumName::Value1, ClassName::EnumName::Value2" ), Equals( std::vector<std::string>{"Value1", "Value2"} ) for: { "Value1", "Value2" } Equals: { "Value1", "Value2" }
EnumToString.tests.cpp:<line number>: passed: parseEnums( "ClassName::EnumName::Value1, ClassName::EnumName::Value2, ClassName::EnumName::Value3" ), Equals( std::vector<std::string>{"Value1", "Value2", "Value3"} ) for: { "Value1", "Value2", "Value3" } Equals: { "Value1", "Value2", "Value3" }
EnumToString.tests.cpp:<line number>: passed: parseEnums( "ClassName::EnumName::Value1,ClassName::EnumName::Value2 , ClassName::EnumName::Value3" ), Equals( std::vector<std::string>{"Value1", "Value2", "Value3"} ) for: { "Value1", "Value2", "Value3" } Equals: { "Value1", "Value2", "Value3" }
Tricky.tests.cpp:<line number>: passed: p == 0 for: 0 == 0 Tricky.tests.cpp:<line number>: passed: p == 0 for: 0 == 0
Message.tests.cpp:<line number>: passed: true with 1 message: 'this MAY be seen IF info is printed for passing assertions' Message.tests.cpp:<line number>: passed: true with 1 message: 'this MAY be seen IF info is printed for passing assertions'
Message.tests.cpp:<line number>: failed: false with 2 messages: 'this SHOULD be seen' and 'this SHOULD also be seen' Message.tests.cpp:<line number>: failed: false with 2 messages: 'this SHOULD be seen' and 'this SHOULD also be seen'
@ -1379,6 +1398,9 @@ String.tests.cpp:<line number>: passed: s == "didn|'t" for: "didn|'t" == "didn|'
Misc.tests.cpp:<line number>: failed: false with 1 message: '3' Misc.tests.cpp:<line number>: failed: false with 1 message: '3'
Message.tests.cpp:<line number>: failed: false with 2 messages: 'hi' and 'i := 7' Message.tests.cpp:<line number>: failed: false with 2 messages: 'hi' and 'i := 7'
Tag.tests.cpp:<line number>: passed: testcase.tags, Catch::VectorContains(std::string("magic-tag")) && Catch::VectorContains(std::string(".")) for: { ".", "magic-tag" } ( Contains: "magic-tag" and Contains: "." ) Tag.tests.cpp:<line number>: passed: testcase.tags, Catch::VectorContains(std::string("magic-tag")) && Catch::VectorContains(std::string(".")) for: { ".", "magic-tag" } ( Contains: "magic-tag" and Contains: "." )
String.tests.cpp:<line number>: passed: splitString("", ',' ), Equals(std::vector<std::string>() ) for: { } Equals: { }
String.tests.cpp:<line number>: passed: splitString("abc", ',' ), Equals(std::vector<std::string>{"abc"} ) for: { "abc" } Equals: { "abc" }
String.tests.cpp:<line number>: passed: splitString("abc,def", ',' ), Equals(std::vector<std::string>{"abc", "def"} ) for: { "abc", "def" } Equals: { "abc", "def" }
Message.tests.cpp:<line number>: failed: false with 4 messages: 'Count 1 to 3...' and '1' and '2' and '3' Message.tests.cpp:<line number>: failed: false with 4 messages: 'Count 1 to 3...' and '1' and '2' and '3'
Message.tests.cpp:<line number>: failed: false with 4 messages: 'Count 4 to 6...' and '4' and '5' and '6' Message.tests.cpp:<line number>: failed: false with 4 messages: 'Count 4 to 6...' and '4' and '5' and '6'
ToStringGeneral.tests.cpp:<line number>: passed: Catch::Detail::stringify( emptyMap ) == "{ }" for: "{ }" == "{ }" ToStringGeneral.tests.cpp:<line number>: passed: Catch::Detail::stringify( emptyMap ) == "{ }" for: "{ }" == "{ }"

View File

@ -1265,6 +1265,6 @@ due to unexpected exception with message:
Why would you throw a std::string? Why would you throw a std::string?
=============================================================================== ===============================================================================
test cases: 257 | 191 passed | 62 failed | 4 failed as expected test cases: 261 | 195 passed | 62 failed | 4 failed as expected
assertions: 1419 | 1276 passed | 122 failed | 21 failed as expected assertions: 1437 | 1294 passed | 122 failed | 21 failed as expected

View File

@ -2225,6 +2225,29 @@ with expansion:
"this string contains 'abc' as a substring" ends with: "this" (case "this string contains 'abc' as a substring" ends with: "this" (case
insensitive) insensitive)
-------------------------------------------------------------------------------
EnumInfo
-------------------------------------------------------------------------------
EnumToString.tests.cpp:<line number>
...............................................................................
EnumToString.tests.cpp:<line number>: PASSED:
CHECK( enumInfo.lookup(0) == "Value1" )
with expansion:
"Value1" == "Value1"
EnumToString.tests.cpp:<line number>: PASSED:
CHECK( enumInfo.lookup(1) == "Value2" )
with expansion:
"Value2" == "Value2"
EnumToString.tests.cpp:<line number>: PASSED:
CHECK( enumInfo.lookup(3) == "{** unexpected value for EnumName: 3**}" )
with expansion:
"{** unexpected value for EnumName: 3**}"
==
"{** unexpected value for EnumName: 3**}"
------------------------------------------------------------------------------- -------------------------------------------------------------------------------
Epsilon only applies to Approx's value Epsilon only applies to Approx's value
------------------------------------------------------------------------------- -------------------------------------------------------------------------------
@ -6684,6 +6707,39 @@ Matchers.tests.cpp:<line number>: PASSED:
with expansion: with expansion:
{ 'a', 'b' } not UnorderedEquals: { 'c', 'b' } { 'a', 'b' } not UnorderedEquals: { 'c', 'b' }
-------------------------------------------------------------------------------
STRINGIFY_ENUM
-------------------------------------------------------------------------------
EnumToString.tests.cpp:<line number>
...............................................................................
EnumToString.tests.cpp:<line number>: PASSED:
REQUIRE( stringify( EnumClass3::Value1 ) == "Value1" )
with expansion:
"Value1" == "Value1"
EnumToString.tests.cpp:<line number>: PASSED:
REQUIRE( stringify( EnumClass3::Value2 ) == "Value2" )
with expansion:
"Value2" == "Value2"
EnumToString.tests.cpp:<line number>: PASSED:
REQUIRE( stringify( EnumClass3::Value3 ) == "Value3" )
with expansion:
"Value3" == "Value3"
EnumToString.tests.cpp:<line number>: PASSED:
REQUIRE( stringify( EnumClass3::Value4 ) == "{** unexpected value for EnumClass3: 3**}" )
with expansion:
"{** unexpected value for EnumClass3: 3**}"
==
"{** unexpected value for EnumClass3: 3**}"
EnumToString.tests.cpp:<line number>: PASSED:
REQUIRE( stringify( ec3 ) == "Value2" )
with expansion:
"Value2" == "Value2"
------------------------------------------------------------------------------- -------------------------------------------------------------------------------
SUCCEED counts as a test pass SUCCEED counts as a test pass
------------------------------------------------------------------------------- -------------------------------------------------------------------------------
@ -10025,6 +10081,62 @@ with expansion:
== ==
"{ { 42, "Arthur" }, { "Ford", 24 } }" "{ { 42, "Arthur" }, { "Ford", 24 } }"
-------------------------------------------------------------------------------
parseEnums
No enums
-------------------------------------------------------------------------------
EnumToString.tests.cpp:<line number>
...............................................................................
EnumToString.tests.cpp:<line number>: PASSED:
CHECK_THAT( parseEnums( "" ), Equals( std::vector<std::string>{} ) )
with expansion:
{ } Equals: { }
-------------------------------------------------------------------------------
parseEnums
One enum value
-------------------------------------------------------------------------------
EnumToString.tests.cpp:<line number>
...............................................................................
EnumToString.tests.cpp:<line number>: PASSED:
CHECK_THAT( parseEnums( "ClassName::EnumName::Value1" ), Equals(std::vector<std::string>{"Value1"} ) )
with expansion:
{ "Value1" } Equals: { "Value1" }
EnumToString.tests.cpp:<line number>: PASSED:
CHECK_THAT( parseEnums( "Value1" ), Equals( std::vector<std::string>{"Value1"} ) )
with expansion:
{ "Value1" } Equals: { "Value1" }
EnumToString.tests.cpp:<line number>: PASSED:
CHECK_THAT( parseEnums( "EnumName::Value1" ), Equals(std::vector<std::string>{"Value1"} ) )
with expansion:
{ "Value1" } Equals: { "Value1" }
-------------------------------------------------------------------------------
parseEnums
Multiple enum values
-------------------------------------------------------------------------------
EnumToString.tests.cpp:<line number>
...............................................................................
EnumToString.tests.cpp:<line number>: PASSED:
CHECK_THAT( parseEnums( "ClassName::EnumName::Value1, ClassName::EnumName::Value2" ), Equals( std::vector<std::string>{"Value1", "Value2"} ) )
with expansion:
{ "Value1", "Value2" } Equals: { "Value1", "Value2" }
EnumToString.tests.cpp:<line number>: PASSED:
CHECK_THAT( parseEnums( "ClassName::EnumName::Value1, ClassName::EnumName::Value2, ClassName::EnumName::Value3" ), Equals( std::vector<std::string>{"Value1", "Value2", "Value3"} ) )
with expansion:
{ "Value1", "Value2", "Value3" } Equals: { "Value1", "Value2", "Value3" }
EnumToString.tests.cpp:<line number>: PASSED:
CHECK_THAT( parseEnums( "ClassName::EnumName::Value1,ClassName::EnumName::Value2 , ClassName::EnumName::Value3" ), Equals( std::vector<std::string>{"Value1", "Value2", "Value3"} ) )
with expansion:
{ "Value1", "Value2", "Value3" } Equals: { "Value1", "Value2", "Value3" }
------------------------------------------------------------------------------- -------------------------------------------------------------------------------
pointer to class pointer to class
------------------------------------------------------------------------------- -------------------------------------------------------------------------------
@ -10272,6 +10384,27 @@ Tag.tests.cpp:<line number>: PASSED:
with expansion: with expansion:
{ ".", "magic-tag" } ( Contains: "magic-tag" and Contains: "." ) { ".", "magic-tag" } ( Contains: "magic-tag" and Contains: "." )
-------------------------------------------------------------------------------
splitString
-------------------------------------------------------------------------------
String.tests.cpp:<line number>
...............................................................................
String.tests.cpp:<line number>: PASSED:
CHECK_THAT( splitString("", ',' ), Equals(std::vector<std::string>() ) )
with expansion:
{ } Equals: { }
String.tests.cpp:<line number>: PASSED:
CHECK_THAT( splitString("abc", ',' ), Equals(std::vector<std::string>{"abc"} ) )
with expansion:
{ "abc" } Equals: { "abc" }
String.tests.cpp:<line number>: PASSED:
CHECK_THAT( splitString("abc,def", ',' ), Equals(std::vector<std::string>{"abc", "def"} ) )
with expansion:
{ "abc", "def" } Equals: { "abc", "def" }
------------------------------------------------------------------------------- -------------------------------------------------------------------------------
stacks unscoped info in loops stacks unscoped info in loops
------------------------------------------------------------------------------- -------------------------------------------------------------------------------
@ -11113,6 +11246,6 @@ Misc.tests.cpp:<line number>
Misc.tests.cpp:<line number>: PASSED: Misc.tests.cpp:<line number>: PASSED:
=============================================================================== ===============================================================================
test cases: 257 | 176 passed | 77 failed | 4 failed as expected test cases: 261 | 180 passed | 77 failed | 4 failed as expected
assertions: 1435 | 1276 passed | 138 failed | 21 failed as expected assertions: 1453 | 1294 passed | 138 failed | 21 failed as expected

View File

@ -5,7 +5,7 @@
<property name="random-seed" value="1"/> <property name="random-seed" value="1"/>
</properties> </properties>
loose text artifact loose text artifact
<testsuite name="<exe-name>" errors="17" failures="122" tests="1436" hostname="tbd" time="{duration}" timestamp="{iso8601-timestamp}"> <testsuite name="<exe-name>" errors="17" failures="122" tests="1454" hostname="tbd" time="{duration}" timestamp="{iso8601-timestamp}">
<testcase classname="<exe-name>.global" name="# A test name that starts with a #" time="{duration}"/> <testcase classname="<exe-name>.global" name="# A test name that starts with a #" time="{duration}"/>
<testcase classname="<exe-name>.global" name="#1005: Comparing pointer to int and long (NULL can be either on various systems)" time="{duration}"/> <testcase classname="<exe-name>.global" name="#1005: Comparing pointer to int and long (NULL can be either on various systems)" time="{duration}"/>
<testcase classname="<exe-name>.global" name="#1027" time="{duration}"/> <testcase classname="<exe-name>.global" name="#1027" time="{duration}"/>
@ -234,6 +234,7 @@ Matchers.tests.cpp:<line number>
Matchers.tests.cpp:<line number> Matchers.tests.cpp:<line number>
</failure> </failure>
</testcase> </testcase>
<testcase classname="<exe-name>.global" name="EnumInfo" time="{duration}"/>
<testcase classname="<exe-name>.global" name="Epsilon only applies to Approx's value" time="{duration}"/> <testcase classname="<exe-name>.global" name="Epsilon only applies to Approx's value" time="{duration}"/>
<testcase classname="<exe-name>.global" name="Equality checks that should fail" time="{duration}"> <testcase classname="<exe-name>.global" name="Equality checks that should fail" time="{duration}">
<failure message="7 == 6" type="CHECK"> <failure message="7 == 6" type="CHECK">
@ -615,6 +616,7 @@ Matchers.tests.cpp:<line number>
</failure> </failure>
</testcase> </testcase>
<testcase classname="<exe-name>.global" name="Regression test #1" time="{duration}"/> <testcase classname="<exe-name>.global" name="Regression test #1" time="{duration}"/>
<testcase classname="<exe-name>.global" name="STRINGIFY_ENUM" time="{duration}"/>
<testcase classname="<exe-name>.global" name="SUCCEED counts as a test pass" time="{duration}"/> <testcase classname="<exe-name>.global" name="SUCCEED counts as a test pass" time="{duration}"/>
<testcase classname="<exe-name>.global" name="SUCCEED does not require an argument" time="{duration}"/> <testcase classname="<exe-name>.global" name="SUCCEED does not require an argument" time="{duration}"/>
<testcase classname="<exe-name>.Fixture" name="Scenario: BDD tests requiring Fixtures to provide commonly-accessed data or methods/Given: No operations precede me" time="{duration}"/> <testcase classname="<exe-name>.Fixture" name="Scenario: BDD tests requiring Fixtures to provide commonly-accessed data or methods/Given: No operations precede me" time="{duration}"/>
@ -945,6 +947,9 @@ Message.tests.cpp:<line number>
<testcase classname="<exe-name>.global" name="null strings" time="{duration}"/> <testcase classname="<exe-name>.global" name="null strings" time="{duration}"/>
<testcase classname="<exe-name>.global" name="null_ptr" time="{duration}"/> <testcase classname="<exe-name>.global" name="null_ptr" time="{duration}"/>
<testcase classname="<exe-name>.global" name="pair&lt;pair&lt;int,const char *,pair&lt;std::string,int> > -> toString" time="{duration}"/> <testcase classname="<exe-name>.global" name="pair&lt;pair&lt;int,const char *,pair&lt;std::string,int> > -> toString" time="{duration}"/>
<testcase classname="<exe-name>.global" name="parseEnums/No enums" time="{duration}"/>
<testcase classname="<exe-name>.global" name="parseEnums/One enum value" time="{duration}"/>
<testcase classname="<exe-name>.global" name="parseEnums/Multiple enum values" time="{duration}"/>
<testcase classname="<exe-name>.global" name="pointer to class" time="{duration}"/> <testcase classname="<exe-name>.global" name="pointer to class" time="{duration}"/>
<testcase classname="<exe-name>.global" name="print unscoped info if passing unscoped info is printed" time="{duration}"/> <testcase classname="<exe-name>.global" name="print unscoped info if passing unscoped info is printed" time="{duration}"/>
<testcase classname="<exe-name>.global" name="prints unscoped info on failure" time="{duration}"> <testcase classname="<exe-name>.global" name="prints unscoped info on failure" time="{duration}">
@ -983,6 +988,7 @@ Message.tests.cpp:<line number>
</failure> </failure>
</testcase> </testcase>
<testcase classname="<exe-name>.global" name="shortened hide tags are split apart" time="{duration}"/> <testcase classname="<exe-name>.global" name="shortened hide tags are split apart" time="{duration}"/>
<testcase classname="<exe-name>.global" name="splitString" time="{duration}"/>
<testcase classname="<exe-name>.global" name="stacks unscoped info in loops" time="{duration}"> <testcase classname="<exe-name>.global" name="stacks unscoped info in loops" time="{duration}">
<failure message="false" type="CHECK"> <failure message="false" type="CHECK">
Count 1 to 3... Count 1 to 3...

View File

@ -2670,6 +2670,35 @@ Nor would this
</Expression> </Expression>
<OverallResult success="false"/> <OverallResult success="false"/>
</TestCase> </TestCase>
<TestCase name="EnumInfo" filename="projects/<exe-name>/UsageTests/EnumToString.tests.cpp" >
<Expression success="true" type="CHECK" filename="projects/<exe-name>/UsageTests/EnumToString.tests.cpp" >
<Original>
enumInfo.lookup(0) == "Value1"
</Original>
<Expanded>
"Value1" == "Value1"
</Expanded>
</Expression>
<Expression success="true" type="CHECK" filename="projects/<exe-name>/UsageTests/EnumToString.tests.cpp" >
<Original>
enumInfo.lookup(1) == "Value2"
</Original>
<Expanded>
"Value2" == "Value2"
</Expanded>
</Expression>
<Expression success="true" type="CHECK" filename="projects/<exe-name>/UsageTests/EnumToString.tests.cpp" >
<Original>
enumInfo.lookup(3) == "{** unexpected value for EnumName: 3**}"
</Original>
<Expanded>
"{** unexpected value for EnumName: 3**}"
==
"{** unexpected value for EnumName: 3**}"
</Expanded>
</Expression>
<OverallResult success="true"/>
</TestCase>
<TestCase name="Epsilon only applies to Approx's value" tags="[Approx]" filename="projects/<exe-name>/UsageTests/Approx.tests.cpp" > <TestCase name="Epsilon only applies to Approx's value" tags="[Approx]" filename="projects/<exe-name>/UsageTests/Approx.tests.cpp" >
<Expression success="true" type="REQUIRE" filename="projects/<exe-name>/UsageTests/Approx.tests.cpp" > <Expression success="true" type="REQUIRE" filename="projects/<exe-name>/UsageTests/Approx.tests.cpp" >
<Original> <Original>
@ -8374,6 +8403,51 @@ Nor would this
</Expression> </Expression>
<OverallResult success="true"/> <OverallResult success="true"/>
</TestCase> </TestCase>
<TestCase name="STRINGIFY_ENUM" filename="projects/<exe-name>/UsageTests/EnumToString.tests.cpp" >
<Expression success="true" type="REQUIRE" filename="projects/<exe-name>/UsageTests/EnumToString.tests.cpp" >
<Original>
stringify( EnumClass3::Value1 ) == "Value1"
</Original>
<Expanded>
"Value1" == "Value1"
</Expanded>
</Expression>
<Expression success="true" type="REQUIRE" filename="projects/<exe-name>/UsageTests/EnumToString.tests.cpp" >
<Original>
stringify( EnumClass3::Value2 ) == "Value2"
</Original>
<Expanded>
"Value2" == "Value2"
</Expanded>
</Expression>
<Expression success="true" type="REQUIRE" filename="projects/<exe-name>/UsageTests/EnumToString.tests.cpp" >
<Original>
stringify( EnumClass3::Value3 ) == "Value3"
</Original>
<Expanded>
"Value3" == "Value3"
</Expanded>
</Expression>
<Expression success="true" type="REQUIRE" filename="projects/<exe-name>/UsageTests/EnumToString.tests.cpp" >
<Original>
stringify( EnumClass3::Value4 ) == "{** unexpected value for EnumClass3: 3**}"
</Original>
<Expanded>
"{** unexpected value for EnumClass3: 3**}"
==
"{** unexpected value for EnumClass3: 3**}"
</Expanded>
</Expression>
<Expression success="true" type="REQUIRE" filename="projects/<exe-name>/UsageTests/EnumToString.tests.cpp" >
<Original>
stringify( ec3 ) == "Value2"
</Original>
<Expanded>
"Value2" == "Value2"
</Expanded>
</Expression>
<OverallResult success="true"/>
</TestCase>
<TestCase name="SUCCEED counts as a test pass" tags="[messages]" filename="projects/<exe-name>/UsageTests/Message.tests.cpp" > <TestCase name="SUCCEED counts as a test pass" tags="[messages]" filename="projects/<exe-name>/UsageTests/Message.tests.cpp" >
<OverallResult success="true"/> <OverallResult success="true"/>
</TestCase> </TestCase>
@ -12197,6 +12271,74 @@ loose text artifact
</Expression> </Expression>
<OverallResult success="true"/> <OverallResult success="true"/>
</TestCase> </TestCase>
<TestCase name="parseEnums" tags="[Strings][enums]" filename="projects/<exe-name>/UsageTests/EnumToString.tests.cpp" >
<Section name="No enums" filename="projects/<exe-name>/UsageTests/EnumToString.tests.cpp" >
<Expression success="true" type="CHECK_THAT" filename="projects/<exe-name>/UsageTests/EnumToString.tests.cpp" >
<Original>
parseEnums( "" ), Equals( std::vector&lt;std::string>{} )
</Original>
<Expanded>
{ } Equals: { }
</Expanded>
</Expression>
<OverallResults successes="1" failures="0" expectedFailures="0"/>
</Section>
<Section name="One enum value" filename="projects/<exe-name>/UsageTests/EnumToString.tests.cpp" >
<Expression success="true" type="CHECK_THAT" filename="projects/<exe-name>/UsageTests/EnumToString.tests.cpp" >
<Original>
parseEnums( "ClassName::EnumName::Value1" ), Equals(std::vector&lt;std::string>{"Value1"} )
</Original>
<Expanded>
{ "Value1" } Equals: { "Value1" }
</Expanded>
</Expression>
<Expression success="true" type="CHECK_THAT" filename="projects/<exe-name>/UsageTests/EnumToString.tests.cpp" >
<Original>
parseEnums( "Value1" ), Equals( std::vector&lt;std::string>{"Value1"} )
</Original>
<Expanded>
{ "Value1" } Equals: { "Value1" }
</Expanded>
</Expression>
<Expression success="true" type="CHECK_THAT" filename="projects/<exe-name>/UsageTests/EnumToString.tests.cpp" >
<Original>
parseEnums( "EnumName::Value1" ), Equals(std::vector&lt;std::string>{"Value1"} )
</Original>
<Expanded>
{ "Value1" } Equals: { "Value1" }
</Expanded>
</Expression>
<OverallResults successes="3" failures="0" expectedFailures="0"/>
</Section>
<Section name="Multiple enum values" filename="projects/<exe-name>/UsageTests/EnumToString.tests.cpp" >
<Expression success="true" type="CHECK_THAT" filename="projects/<exe-name>/UsageTests/EnumToString.tests.cpp" >
<Original>
parseEnums( "ClassName::EnumName::Value1, ClassName::EnumName::Value2" ), Equals( std::vector&lt;std::string>{"Value1", "Value2"} )
</Original>
<Expanded>
{ "Value1", "Value2" } Equals: { "Value1", "Value2" }
</Expanded>
</Expression>
<Expression success="true" type="CHECK_THAT" filename="projects/<exe-name>/UsageTests/EnumToString.tests.cpp" >
<Original>
parseEnums( "ClassName::EnumName::Value1, ClassName::EnumName::Value2, ClassName::EnumName::Value3" ), Equals( std::vector&lt;std::string>{"Value1", "Value2", "Value3"} )
</Original>
<Expanded>
{ "Value1", "Value2", "Value3" } Equals: { "Value1", "Value2", "Value3" }
</Expanded>
</Expression>
<Expression success="true" type="CHECK_THAT" filename="projects/<exe-name>/UsageTests/EnumToString.tests.cpp" >
<Original>
parseEnums( "ClassName::EnumName::Value1,ClassName::EnumName::Value2 , ClassName::EnumName::Value3" ), Equals( std::vector&lt;std::string>{"Value1", "Value2", "Value3"} )
</Original>
<Expanded>
{ "Value1", "Value2", "Value3" } Equals: { "Value1", "Value2", "Value3" }
</Expanded>
</Expression>
<OverallResults successes="3" failures="0" expectedFailures="0"/>
</Section>
<OverallResult success="true"/>
</TestCase>
<TestCase name="pointer to class" tags="[Tricky]" filename="projects/<exe-name>/UsageTests/Tricky.tests.cpp" > <TestCase name="pointer to class" tags="[Tricky]" filename="projects/<exe-name>/UsageTests/Tricky.tests.cpp" >
<Expression success="true" type="REQUIRE" filename="projects/<exe-name>/UsageTests/Tricky.tests.cpp" > <Expression success="true" type="REQUIRE" filename="projects/<exe-name>/UsageTests/Tricky.tests.cpp" >
<Original> <Original>
@ -12494,6 +12636,33 @@ loose text artifact
</Expression> </Expression>
<OverallResult success="true"/> <OverallResult success="true"/>
</TestCase> </TestCase>
<TestCase name="splitString" tags="[Strings]" filename="projects/<exe-name>/IntrospectiveTests/String.tests.cpp" >
<Expression success="true" type="CHECK_THAT" filename="projects/<exe-name>/IntrospectiveTests/String.tests.cpp" >
<Original>
splitString("", ',' ), Equals(std::vector&lt;std::string>() )
</Original>
<Expanded>
{ } Equals: { }
</Expanded>
</Expression>
<Expression success="true" type="CHECK_THAT" filename="projects/<exe-name>/IntrospectiveTests/String.tests.cpp" >
<Original>
splitString("abc", ',' ), Equals(std::vector&lt;std::string>{"abc"} )
</Original>
<Expanded>
{ "abc" } Equals: { "abc" }
</Expanded>
</Expression>
<Expression success="true" type="CHECK_THAT" filename="projects/<exe-name>/IntrospectiveTests/String.tests.cpp" >
<Original>
splitString("abc,def", ',' ), Equals(std::vector&lt;std::string>{"abc", "def"} )
</Original>
<Expanded>
{ "abc", "def" } Equals: { "abc", "def" }
</Expanded>
</Expression>
<OverallResult success="true"/>
</TestCase>
<TestCase name="stacks unscoped info in loops" tags="[.][failing][info][unscoped]" filename="projects/<exe-name>/UsageTests/Message.tests.cpp" > <TestCase name="stacks unscoped info in loops" tags="[.][failing][info][unscoped]" filename="projects/<exe-name>/UsageTests/Message.tests.cpp" >
<Info> <Info>
Count 1 to 3... Count 1 to 3...
@ -13388,7 +13557,7 @@ loose text artifact
</Section> </Section>
<OverallResult success="true"/> <OverallResult success="true"/>
</TestCase> </TestCase>
<OverallResults successes="1276" failures="139" expectedFailures="21"/> <OverallResults successes="1294" failures="139" expectedFailures="21"/>
</Group> </Group>
<OverallResults successes="1276" failures="138" expectedFailures="21"/> <OverallResults successes="1294" failures="138" expectedFailures="21"/>
</Catch> </Catch>

View File

@ -202,3 +202,14 @@ TEST_CASE( "replaceInPlace", "[Strings][StringManip]" ) {
CHECK( s == "didn|'t" ); CHECK( s == "didn|'t" );
} }
} }
TEST_CASE( "splitString", "[Strings]" ) {
using namespace Catch::Matchers;
using Catch::splitString;
CHECK_THAT( splitString("", ',' ), Equals(std::vector<std::string>() ) );
CHECK_THAT( splitString("abc", ',' ), Equals(std::vector<std::string>{"abc"} ) );
CHECK_THAT( splitString("abc,def", ',' ), Equals(std::vector<std::string>{"abc", "def"} ) );
}

View File

@ -64,3 +64,57 @@ TEST_CASE( "toString(enum class w/operator<<)", "[toString][enum][enumClass]" )
EnumClass2 e3 = static_cast<EnumClass2>(10); EnumClass2 e3 = static_cast<EnumClass2>(10);
CHECK( ::Catch::Detail::stringify(e3) == "Unknown enum value 10" ); CHECK( ::Catch::Detail::stringify(e3) == "Unknown enum value 10" );
} }
enum class EnumClass3 { Value1, Value2, Value3, Value4 };
STRINGIFY_ENUM( EnumClass3, EnumClass3::Value1, EnumClass3::Value2, EnumClass3::Value3 )
TEST_CASE( "STRINGIFY_ENUM" ) {
using Catch::Detail::stringify;
REQUIRE( stringify( EnumClass3::Value1 ) == "Value1" );
REQUIRE( stringify( EnumClass3::Value2 ) == "Value2" );
REQUIRE( stringify( EnumClass3::Value3 ) == "Value3" );
REQUIRE( stringify( EnumClass3::Value4 ) == "{** unexpected value for EnumClass3: 3**}" );
EnumClass3 ec3 = EnumClass3 ::Value2;
REQUIRE( stringify( ec3 ) == "Value2" );
}
#include "internal/catch_interfaces_enum_values_registry.h"
TEST_CASE( "EnumInfo" ) {
auto& hub = Catch::getMutableRegistryHub();
auto& reg = hub.getMutableEnumValuesRegistry();
auto const& enumInfo = reg.registerEnum( "EnumName", "EnumName::Value1, EnumName::Value2", {0, 1} );
CHECK( enumInfo.lookup(0) == "Value1" );
CHECK( enumInfo.lookup(1) == "Value2" );
CHECK( enumInfo.lookup(3) == "{** unexpected value for EnumName: 3**}" );
}
#include "internal/catch_enum_values_registry.h"
TEST_CASE( "parseEnums", "[Strings][enums]" ) {
using namespace Catch::Matchers;
using Catch::Detail::parseEnums;
SECTION( "No enums" )
CHECK_THAT( parseEnums( "" ), Equals( std::vector<std::string>{} ) );
SECTION( "One enum value" ) {
CHECK_THAT( parseEnums( "ClassName::EnumName::Value1" ), Equals(std::vector<std::string>{"Value1"} ) );
CHECK_THAT( parseEnums( "Value1" ), Equals( std::vector<std::string>{"Value1"} ) );
CHECK_THAT( parseEnums( "EnumName::Value1" ), Equals(std::vector<std::string>{"Value1"} ) );
}
SECTION( "Multiple enum values" ) {
CHECK_THAT( parseEnums( "ClassName::EnumName::Value1, ClassName::EnumName::Value2" ),
Equals( std::vector<std::string>{"Value1", "Value2"} ) );
CHECK_THAT( parseEnums( "ClassName::EnumName::Value1, ClassName::EnumName::Value2, ClassName::EnumName::Value3" ),
Equals( std::vector<std::string>{"Value1", "Value2", "Value3"} ) );
CHECK_THAT( parseEnums( "ClassName::EnumName::Value1,ClassName::EnumName::Value2 , ClassName::EnumName::Value3" ),
Equals( std::vector<std::string>{"Value1", "Value2", "Value3"} ) );
}
}