1 #include "catch.hpp"
2
3
4 namespace {
5 // Enum without user-provided stream operator
6 enum Enum1 { Enum1Value0, Enum1Value1 };
7
8 // Enum with user-provided stream operator
9 enum Enum2 { Enum2Value0, Enum2Value1 };
10
operator <<(std::ostream & os,Enum2 v)11 std::ostream& operator<<( std::ostream& os, Enum2 v ) {
12 return os << "E2{" << static_cast<int>(v) << "}";
13 }
14 } // end anonymous namespace
15
16 TEST_CASE( "toString(enum)", "[toString][enum]" ) {
17 Enum1 e0 = Enum1Value0;
18 CHECK( ::Catch::Detail::stringify(e0) == "0" );
19 Enum1 e1 = Enum1Value1;
20 CHECK( ::Catch::Detail::stringify(e1) == "1" );
21 }
22
23 TEST_CASE( "toString(enum w/operator<<)", "[toString][enum]" ) {
24 Enum2 e0 = Enum2Value0;
25 CHECK( ::Catch::Detail::stringify(e0) == "E2{0}" );
26 Enum2 e1 = Enum2Value1;
27 CHECK( ::Catch::Detail::stringify(e1) == "E2{1}" );
28 }
29
30 // Enum class without user-provided stream operator
31 namespace {
32 enum class EnumClass1 { EnumClass1Value0, EnumClass1Value1 };
33
34 // Enum class with user-provided stream operator
35 enum class EnumClass2 { EnumClass2Value0, EnumClass2Value1 };
36
operator <<(std::ostream & os,EnumClass2 e2)37 std::ostream& operator<<( std::ostream& os, EnumClass2 e2 ) {
38 switch( static_cast<int>( e2 ) ) {
39 case static_cast<int>( EnumClass2::EnumClass2Value0 ):
40 return os << "E2/V0";
41 case static_cast<int>( EnumClass2::EnumClass2Value1 ):
42 return os << "E2/V1";
43 default:
44 return os << "Unknown enum value " << static_cast<int>( e2 );
45 }
46 }
47
48 } // end anonymous namespace
49
50 TEST_CASE( "toString(enum class)", "[toString][enum][enumClass]" ) {
51 EnumClass1 e0 = EnumClass1::EnumClass1Value0;
52 CHECK( ::Catch::Detail::stringify(e0) == "0" );
53 EnumClass1 e1 = EnumClass1::EnumClass1Value1;
54 CHECK( ::Catch::Detail::stringify(e1) == "1" );
55 }
56
57
58 TEST_CASE( "toString(enum class w/operator<<)", "[toString][enum][enumClass]" ) {
59 EnumClass2 e0 = EnumClass2::EnumClass2Value0;
60 CHECK( ::Catch::Detail::stringify(e0) == "E2/V0" );
61 EnumClass2 e1 = EnumClass2::EnumClass2Value1;
62 CHECK( ::Catch::Detail::stringify(e1) == "E2/V1" );
63
64 auto e3 = static_cast<EnumClass2>(10);
65 CHECK( ::Catch::Detail::stringify(e3) == "Unknown enum value 10" );
66 }
67
68 enum class EnumClass3 { Value1, Value2, Value3, Value4 };
69
CATCH_REGISTER_ENUM(EnumClass3,EnumClass3::Value1,EnumClass3::Value2,EnumClass3::Value3)70 CATCH_REGISTER_ENUM( EnumClass3, EnumClass3::Value1, EnumClass3::Value2, EnumClass3::Value3 )
71
72
73 TEST_CASE( "Enums can quickly have stringification enabled using REGISTER_ENUM" ) {
74 using Catch::Detail::stringify;
75 REQUIRE( stringify( EnumClass3::Value1 ) == "Value1" );
76 REQUIRE( stringify( EnumClass3::Value2 ) == "Value2" );
77 REQUIRE( stringify( EnumClass3::Value3 ) == "Value3" );
78 REQUIRE( stringify( EnumClass3::Value4 ) == "{** unexpected enum value **}" );
79
80 EnumClass3 ec3 = EnumClass3 ::Value2;
81 REQUIRE( stringify( ec3 ) == "Value2" );
82 }
83
84 namespace Bikeshed {
85 enum class Colours { Red, Green, Blue };
86 }
87
88 // Important!: This macro must appear at top level scope - not inside a namespace
89 // 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)90 CATCH_REGISTER_ENUM( Bikeshed::Colours,
91 Bikeshed::Colours::Red,
92 Bikeshed::Colours::Green,
93 Bikeshed::Colours::Blue )
94
95 TEST_CASE( "Enums in namespaces can quickly have stringification enabled using REGISTER_ENUM" ) {
96 using Catch::Detail::stringify;
97 REQUIRE( stringify( Bikeshed::Colours::Red ) == "Red" );
98 REQUIRE( stringify( Bikeshed::Colours::Blue ) == "Blue" );
99 }
100