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