mirror of
https://github.com/catchorg/Catch2.git
synced 2024-12-23 11:43:29 +01:00
Merge branch enum stringification work
This commit is contained in:
commit
46066ede17
@ -6,6 +6,7 @@
|
|||||||
[Catch::StringMaker specialisation](#catchstringmaker-specialisation)<br>
|
[Catch::StringMaker specialisation](#catchstringmaker-specialisation)<br>
|
||||||
[Catch::is_range specialisation](#catchis_range-specialisation)<br>
|
[Catch::is_range specialisation](#catchis_range-specialisation)<br>
|
||||||
[Exceptions](#exceptions)<br>
|
[Exceptions](#exceptions)<br>
|
||||||
|
[Enums](#enums)<br>
|
||||||
|
|
||||||
Catch needs to be able to convert types you use in assertions and logging expressions into strings (for logging and reporting purposes).
|
Catch needs to be able to convert types you use in assertions and logging expressions into strings (for logging and reporting purposes).
|
||||||
Most built-in or std types are supported out of the box but there are two ways that you can tell Catch how to convert your own types (or other, third-party types) into strings.
|
Most built-in or std types are supported out of the box but there are two ways that you can tell Catch how to convert your own types (or other, third-party types) into strings.
|
||||||
@ -66,6 +67,44 @@ CATCH_TRANSLATE_EXCEPTION( MyType& ex ) {
|
|||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
|
## Enums
|
||||||
|
|
||||||
|
Enums that already have a `<<` overload for `std::ostream` will convert to strings as expected.
|
||||||
|
If you only need to convert enums to strings for test reporting purposes you can provide a `StringMaker` specialisations as any other type.
|
||||||
|
However, as a convenience, Catch provides the `REGISTER_ENUM` helper macro that will generate the `StringMaker` specialiation for you with minimal code.
|
||||||
|
Simply provide it the (qualified) enum name, followed by all the enum values, and you're done!
|
||||||
|
|
||||||
|
E.g.
|
||||||
|
|
||||||
|
```
|
||||||
|
enum class Fruits { Banana, Apple, Mango };
|
||||||
|
|
||||||
|
CATCH_REGISTER_ENUM( Fruits, Fruits::Banana, Fruits::Apple, Fruits::Mango );
|
||||||
|
|
||||||
|
TEST_CASE() {
|
||||||
|
REQUIRE( Fruits::Mango == Fruits::Apple );
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
... or if the enum is in a namespace:
|
||||||
|
```
|
||||||
|
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() {
|
||||||
|
REQUIRE( Bikeshed::Colours::Red == Bikeshed::Colours::Blue );
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
[Home](Readme.md#top)
|
[Home](Readme.md#top)
|
||||||
|
65
include/internal/catch_enum_values_registry.cpp
Normal file
65
include/internal/catch_enum_values_registry.cpp
Normal file
@ -0,0 +1,65 @@
|
|||||||
|
/*
|
||||||
|
* 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>
|
||||||
|
#include <cassert>
|
||||||
|
|
||||||
|
namespace Catch {
|
||||||
|
|
||||||
|
IMutableEnumValuesRegistry::~IMutableEnumValuesRegistry() {}
|
||||||
|
|
||||||
|
namespace Detail {
|
||||||
|
|
||||||
|
std::vector<std::string> parseEnums( StringRef enums ) {
|
||||||
|
auto enumValues = splitStringRef( enums, ',' );
|
||||||
|
std::vector<std::string> parsed;
|
||||||
|
parsed.reserve( enumValues.size() );
|
||||||
|
for( auto const& enumValue : enumValues ) {
|
||||||
|
auto identifiers = splitStringRef( enumValue, ':' );
|
||||||
|
parsed.push_back( Catch::trim( identifiers.back() ) );
|
||||||
|
}
|
||||||
|
return parsed;
|
||||||
|
}
|
||||||
|
|
||||||
|
EnumInfo::~EnumInfo() {}
|
||||||
|
|
||||||
|
StringRef EnumInfo::lookup( int value ) const {
|
||||||
|
for( auto const& valueToName : m_values ) {
|
||||||
|
if( valueToName.first == value )
|
||||||
|
return valueToName.second;
|
||||||
|
}
|
||||||
|
return "{** unexpected enum value **}";
|
||||||
|
}
|
||||||
|
|
||||||
|
std::unique_ptr<EnumInfo> makeEnumInfo( StringRef enumName, StringRef allValueNames, std::vector<int> const& values ) {
|
||||||
|
std::unique_ptr<EnumInfo> enumInfo( new 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.push_back({ value, valueNames[i++] });
|
||||||
|
|
||||||
|
return enumInfo;
|
||||||
|
}
|
||||||
|
|
||||||
|
EnumInfo const& EnumValuesRegistry::registerEnum( StringRef enumName, StringRef allValueNames, std::vector<int> const& values ) {
|
||||||
|
auto enumInfo = makeEnumInfo( enumName, allValueNames, values );
|
||||||
|
EnumInfo* raw = enumInfo.get();
|
||||||
|
m_enumInfos.push_back( std::move( enumInfo ) );
|
||||||
|
return *raw;
|
||||||
|
}
|
||||||
|
|
||||||
|
} // Detail
|
||||||
|
} // Catch
|
||||||
|
|
34
include/internal/catch_enum_values_registry.h
Normal file
34
include/internal/catch_enum_values_registry.h
Normal file
@ -0,0 +1,34 @@
|
|||||||
|
/*
|
||||||
|
* 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 {
|
||||||
|
|
||||||
|
std::unique_ptr<EnumInfo> makeEnumInfo( StringRef enumName, StringRef allValueNames, std::vector<int> const& values );
|
||||||
|
|
||||||
|
class EnumValuesRegistry : public IMutableEnumValuesRegistry {
|
||||||
|
|
||||||
|
std::vector<std::unique_ptr<EnumInfo>> m_enumInfos;
|
||||||
|
|
||||||
|
EnumInfo 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
|
45
include/internal/catch_interfaces_enum_values_registry.h
Normal file
45
include/internal/catch_interfaces_enum_values_registry.h
Normal file
@ -0,0 +1,45 @@
|
|||||||
|
/*
|
||||||
|
* 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 {
|
||||||
|
|
||||||
|
namespace Detail {
|
||||||
|
struct EnumInfo {
|
||||||
|
StringRef m_name;
|
||||||
|
std::vector<std::pair<int, std::string>> m_values;
|
||||||
|
|
||||||
|
~EnumInfo();
|
||||||
|
|
||||||
|
StringRef lookup( int value ) const;
|
||||||
|
};
|
||||||
|
} // namespace Detail
|
||||||
|
|
||||||
|
struct IMutableEnumValuesRegistry {
|
||||||
|
virtual ~IMutableEnumValuesRegistry();
|
||||||
|
|
||||||
|
virtual Detail::EnumInfo const& registerEnum( StringRef enumName, StringRef allEnums, std::vector<int> const& values ) = 0;
|
||||||
|
|
||||||
|
template<typename E>
|
||||||
|
Detail::EnumInfo 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
|
@ -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();
|
||||||
|
@ -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;
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -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<StringRef> splitStringRef( StringRef str, char delimiter ) {
|
||||||
|
std::vector<StringRef> 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 )
|
||||||
|
@ -7,8 +7,11 @@
|
|||||||
#ifndef TWOBLUECUBES_CATCH_STRING_MANIP_H_INCLUDED
|
#ifndef TWOBLUECUBES_CATCH_STRING_MANIP_H_INCLUDED
|
||||||
#define TWOBLUECUBES_CATCH_STRING_MANIP_H_INCLUDED
|
#define TWOBLUECUBES_CATCH_STRING_MANIP_H_INCLUDED
|
||||||
|
|
||||||
|
#include "catch_stringref.h"
|
||||||
|
|
||||||
#include <string>
|
#include <string>
|
||||||
#include <iosfwd>
|
#include <iosfwd>
|
||||||
|
#include <vector>
|
||||||
|
|
||||||
namespace Catch {
|
namespace Catch {
|
||||||
|
|
||||||
@ -20,6 +23,9 @@ namespace Catch {
|
|||||||
void toLowerInPlace( std::string& s );
|
void toLowerInPlace( std::string& s );
|
||||||
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 );
|
||||||
|
|
||||||
|
// !!! Be aware, returns refs into original string - make sure original string outlives them
|
||||||
|
std::vector<StringRef> splitStringRef( StringRef str, char delimiter );
|
||||||
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 );
|
||||||
|
|
||||||
struct pluralise {
|
struct pluralise {
|
||||||
|
@ -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,15 @@ struct ratio_string<std::milli> {
|
|||||||
}
|
}
|
||||||
#endif // CATCH_CONFIG_ENABLE_CHRONO_STRINGMAKER
|
#endif // CATCH_CONFIG_ENABLE_CHRONO_STRINGMAKER
|
||||||
|
|
||||||
|
#define INTERNAL_CATCH_REGISTER_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 ) ); \
|
||||||
|
} \
|
||||||
|
};
|
||||||
|
|
||||||
|
#define CATCH_REGISTER_ENUM( enumName, ... ) INTERNAL_CATCH_REGISTER_ENUM( enumName, __VA_ARGS__ )
|
||||||
|
|
||||||
#ifdef _MSC_VER
|
#ifdef _MSC_VER
|
||||||
#pragma warning(pop)
|
#pragma warning(pop)
|
||||||
|
@ -22,6 +22,7 @@ set(TEST_SOURCES
|
|||||||
${SELF_TEST_DIR}/IntrospectiveTests/Tag.tests.cpp
|
${SELF_TEST_DIR}/IntrospectiveTests/Tag.tests.cpp
|
||||||
${SELF_TEST_DIR}/IntrospectiveTests/String.tests.cpp
|
${SELF_TEST_DIR}/IntrospectiveTests/String.tests.cpp
|
||||||
${SELF_TEST_DIR}/IntrospectiveTests/Xml.tests.cpp
|
${SELF_TEST_DIR}/IntrospectiveTests/Xml.tests.cpp
|
||||||
|
${SELF_TEST_DIR}/IntrospectiveTests/ToString.tests.cpp
|
||||||
${SELF_TEST_DIR}/UsageTests/Approx.tests.cpp
|
${SELF_TEST_DIR}/UsageTests/Approx.tests.cpp
|
||||||
${SELF_TEST_DIR}/UsageTests/BDD.tests.cpp
|
${SELF_TEST_DIR}/UsageTests/BDD.tests.cpp
|
||||||
${SELF_TEST_DIR}/UsageTests/Benchmark.tests.cpp
|
${SELF_TEST_DIR}/UsageTests/Benchmark.tests.cpp
|
||||||
@ -97,6 +98,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 +109,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 +185,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
|
||||||
|
@ -202,3 +202,15 @@ TEST_CASE( "replaceInPlace", "[Strings][StringManip]" ) {
|
|||||||
CHECK( s == "didn|'t" );
|
CHECK( s == "didn|'t" );
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
TEST_CASE( "splitString", "[Strings]" ) {
|
||||||
|
using namespace Catch::Matchers;
|
||||||
|
using Catch::splitStringRef;
|
||||||
|
using Catch::StringRef;
|
||||||
|
|
||||||
|
CHECK_THAT( splitStringRef("", ',' ), Equals(std::vector<StringRef>() ) );
|
||||||
|
CHECK_THAT( splitStringRef("abc", ',' ), Equals(std::vector<StringRef>{"abc"} ) );
|
||||||
|
CHECK_THAT( splitStringRef("abc,def", ',' ), Equals(std::vector<StringRef>{"abc", "def"} ) );
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
42
projects/SelfTest/IntrospectiveTests/ToString.tests.cpp
Normal file
42
projects/SelfTest/IntrospectiveTests/ToString.tests.cpp
Normal file
@ -0,0 +1,42 @@
|
|||||||
|
#include "catch.hpp"
|
||||||
|
|
||||||
|
#include "internal/catch_enum_values_registry.h"
|
||||||
|
|
||||||
|
enum class EnumClass3 { Value1, Value2, Value3, Value4 };
|
||||||
|
|
||||||
|
|
||||||
|
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"} ) );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST_CASE( "Directly creating an EnumInfo" ) {
|
||||||
|
|
||||||
|
using namespace Catch::Detail;
|
||||||
|
std::unique_ptr<EnumInfo> 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 **}" );
|
||||||
|
}
|
@ -61,6 +61,39 @@ TEST_CASE( "toString(enum class w/operator<<)", "[toString][enum][enumClass]" )
|
|||||||
EnumClass2 e1 = EnumClass2::EnumClass2Value1;
|
EnumClass2 e1 = EnumClass2::EnumClass2Value1;
|
||||||
CHECK( ::Catch::Detail::stringify(e1) == "E2/V1" );
|
CHECK( ::Catch::Detail::stringify(e1) == "E2/V1" );
|
||||||
|
|
||||||
EnumClass2 e3 = static_cast<EnumClass2>(10);
|
auto 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 };
|
||||||
|
|
||||||
|
CATCH_REGISTER_ENUM( EnumClass3, EnumClass3::Value1, EnumClass3::Value2, EnumClass3::Value3 )
|
||||||
|
|
||||||
|
|
||||||
|
TEST_CASE( "Enums can quickly have stringification enabled using REGISTER_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 enum value **}" );
|
||||||
|
|
||||||
|
EnumClass3 ec3 = EnumClass3 ::Value2;
|
||||||
|
REQUIRE( stringify( ec3 ) == "Value2" );
|
||||||
|
}
|
||||||
|
|
||||||
|
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 REGISTER_ENUM" ) {
|
||||||
|
using Catch::Detail::stringify;
|
||||||
|
REQUIRE( stringify( Bikeshed::Colours::Red ) == "Red" );
|
||||||
|
REQUIRE( stringify( Bikeshed::Colours::Blue ) == "Blue" );
|
||||||
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user