mirror of
				https://github.com/catchorg/Catch2.git
				synced 2025-11-04 05:59:32 +01:00 
			
		
		
		
	Merge branch enum stringification work
This commit is contained in:
		@@ -6,6 +6,7 @@
 | 
			
		||||
[Catch::StringMaker specialisation](#catchstringmaker-specialisation)<br>
 | 
			
		||||
[Catch::is_range specialisation](#catchis_range-specialisation)<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).
 | 
			
		||||
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)
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										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 IReporterFactory;
 | 
			
		||||
    struct ITagAliasRegistry;
 | 
			
		||||
    struct IMutableEnumValuesRegistry;
 | 
			
		||||
 | 
			
		||||
    class StartupExceptionRegistry;
 | 
			
		||||
 | 
			
		||||
    using IReporterFactoryPtr = std::shared_ptr<IReporterFactory>;
 | 
			
		||||
@@ -32,7 +34,6 @@ namespace Catch {
 | 
			
		||||
        virtual IReporterRegistry const& getReporterRegistry() const = 0;
 | 
			
		||||
        virtual ITestCaseRegistry const& getTestCaseRegistry() const = 0;
 | 
			
		||||
        virtual ITagAliasRegistry const& getTagAliasRegistry() const = 0;
 | 
			
		||||
 | 
			
		||||
        virtual IExceptionTranslatorRegistry const& getExceptionTranslatorRegistry() const = 0;
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
@@ -47,6 +48,7 @@ namespace Catch {
 | 
			
		||||
        virtual void registerTranslator( const IExceptionTranslator* 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();
 | 
			
		||||
 
 | 
			
		||||
@@ -15,6 +15,7 @@
 | 
			
		||||
#include "catch_tag_alias_registry.h"
 | 
			
		||||
#include "catch_startup_exception_registry.h"
 | 
			
		||||
#include "catch_singletons.hpp"
 | 
			
		||||
#include "catch_enum_values_registry.h"
 | 
			
		||||
 | 
			
		||||
namespace Catch {
 | 
			
		||||
 | 
			
		||||
@@ -60,6 +61,9 @@ namespace Catch {
 | 
			
		||||
            void registerStartupException() noexcept override {
 | 
			
		||||
                m_exceptionRegistry.add(std::current_exception());
 | 
			
		||||
            }
 | 
			
		||||
            IMutableEnumValuesRegistry& getMutableEnumValuesRegistry() override {
 | 
			
		||||
                return m_enumValuesRegistry;
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
        private:
 | 
			
		||||
            TestRegistry m_testCaseRegistry;
 | 
			
		||||
@@ -67,6 +71,7 @@ namespace Catch {
 | 
			
		||||
            ExceptionTranslatorRegistry m_exceptionTranslatorRegistry;
 | 
			
		||||
            TagAliasRegistry m_tagAliasRegistry;
 | 
			
		||||
            StartupExceptionRegistry m_exceptionRegistry;
 | 
			
		||||
            Detail::EnumValuesRegistry m_enumValuesRegistry;
 | 
			
		||||
        };
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
@@ -6,11 +6,13 @@
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
#include "catch_string_manip.h"
 | 
			
		||||
#include "catch_stringref.h"
 | 
			
		||||
 | 
			
		||||
#include <algorithm>
 | 
			
		||||
#include <ostream>
 | 
			
		||||
#include <cstring>
 | 
			
		||||
#include <cctype>
 | 
			
		||||
#include <vector>
 | 
			
		||||
 | 
			
		||||
namespace Catch {
 | 
			
		||||
 | 
			
		||||
@@ -65,6 +67,21 @@ namespace Catch {
 | 
			
		||||
        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 )
 | 
			
		||||
    :   m_count( count ),
 | 
			
		||||
        m_label( label )
 | 
			
		||||
 
 | 
			
		||||
@@ -7,8 +7,11 @@
 | 
			
		||||
#ifndef TWOBLUECUBES_CATCH_STRING_MANIP_H_INCLUDED
 | 
			
		||||
#define TWOBLUECUBES_CATCH_STRING_MANIP_H_INCLUDED
 | 
			
		||||
 | 
			
		||||
#include "catch_stringref.h"
 | 
			
		||||
 | 
			
		||||
#include <string>
 | 
			
		||||
#include <iosfwd>
 | 
			
		||||
#include <vector>
 | 
			
		||||
 | 
			
		||||
namespace Catch {
 | 
			
		||||
 | 
			
		||||
@@ -20,6 +23,9 @@ namespace Catch {
 | 
			
		||||
    void toLowerInPlace( std::string& s );
 | 
			
		||||
    std::string toLower( std::string const& s );
 | 
			
		||||
    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 );
 | 
			
		||||
 | 
			
		||||
    struct pluralise {
 | 
			
		||||
 
 | 
			
		||||
@@ -15,6 +15,7 @@
 | 
			
		||||
#include <string>
 | 
			
		||||
#include "catch_compiler_capabilities.h"
 | 
			
		||||
#include "catch_stream.h"
 | 
			
		||||
#include "catch_interfaces_enum_values_registry.h"
 | 
			
		||||
 | 
			
		||||
#ifdef CATCH_CONFIG_CPP17_STRING_VIEW
 | 
			
		||||
#include <string_view>
 | 
			
		||||
@@ -639,6 +640,15 @@ struct ratio_string<std::milli> {
 | 
			
		||||
}
 | 
			
		||||
#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
 | 
			
		||||
#pragma warning(pop)
 | 
			
		||||
 
 | 
			
		||||
@@ -22,6 +22,7 @@ set(TEST_SOURCES
 | 
			
		||||
        ${SELF_TEST_DIR}/IntrospectiveTests/Tag.tests.cpp
 | 
			
		||||
        ${SELF_TEST_DIR}/IntrospectiveTests/String.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/BDD.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_default_main.hpp
 | 
			
		||||
        ${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_exception_translator_registry.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_interfaces_capture.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_registry_hub.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_decomposer.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_exception_translator_registry.cpp
 | 
			
		||||
        ${HEADER_DIR}/internal/catch_fatal_condition.cpp
 | 
			
		||||
 
 | 
			
		||||
@@ -202,3 +202,15 @@ TEST_CASE( "replaceInPlace", "[Strings][StringManip]" ) {
 | 
			
		||||
        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;
 | 
			
		||||
    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" );
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
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" );
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
		Reference in New Issue
	
	Block a user