// Licensed under the MIT License . // SPDX-License-Identifier: MIT // Copyright (c) 2019 Daniil Goncharov . // // Permission is hereby granted, free of charge, to any person obtaining a copy // of this software and associated documentation files (the "Software"), to deal // in the Software without restriction, including without limitation the rights // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell // copies of the Software, and to permit persons to whom the Software is // furnished to do so, subject to the following conditions: // // The above copyright notice and this permission notice shall be included in all // copies or substantial portions of the Software. // // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE // SOFTWARE. #define CATCH_CONFIG_MAIN #include #define MAGIC_ENUM_RANGE_MIN -120 #define MAGIC_ENUM_RANGE_MAX 120 #include #include #include #include enum class Color { RED = -12, GREEN = 7, BLUE = 15 }; enum class Numbers : char { one = 10, two = 20, three = 30, many = 127 }; enum Directions { Up = 85, Down = -42, Right = 120, Left = -120 }; enum number : unsigned long { zero = 0, one = 100, two = 200, three = 300, four = 400 }; namespace magic_enum { template <> struct enum_range { static constexpr int min = 100; static constexpr int max = 300; }; } TEST_CASE("enum_cast") { SECTION("string") { #if defined(_MSC_VER) && _MSC_VER < 1920 # define constexpr // Visual Studio 2017 have bug with string_view constexpr compare. #endif constexpr auto cr = magic_enum::enum_cast("RED"); REQUIRE(cr.value() == Color::RED); REQUIRE(magic_enum::enum_cast("GREEN").value() == Color::GREEN); REQUIRE(magic_enum::enum_cast("BLUE").value() == Color::BLUE); REQUIRE_FALSE(magic_enum::enum_cast("None").has_value()); constexpr auto no = magic_enum::enum_cast("one"); REQUIRE(no.value() == Numbers::one); REQUIRE(magic_enum::enum_cast("two").value() == Numbers::two); REQUIRE(magic_enum::enum_cast("three").value() == Numbers::three); REQUIRE_FALSE(magic_enum::enum_cast("many").has_value()); REQUIRE_FALSE(magic_enum::enum_cast("None").has_value()); constexpr auto dr = magic_enum::enum_cast("Right"); REQUIRE(magic_enum::enum_cast("Up").value() == Directions::Up); REQUIRE(magic_enum::enum_cast("Down").value() == Directions::Down); REQUIRE(dr.value() == Directions::Right); REQUIRE(magic_enum::enum_cast("Left").value() == Directions::Left); REQUIRE_FALSE(magic_enum::enum_cast("None").has_value()); constexpr auto nt = magic_enum::enum_cast("three"); REQUIRE(magic_enum::enum_cast("one").value() == number::one); REQUIRE(magic_enum::enum_cast("two").value() == number::two); REQUIRE(nt.value() == number::three); REQUIRE_FALSE(magic_enum::enum_cast("zero").has_value()); REQUIRE_FALSE(magic_enum::enum_cast("four").has_value()); REQUIRE_FALSE(magic_enum::enum_cast("None").has_value()); #undef constexpr } SECTION("integer") { constexpr auto cr = magic_enum::enum_cast(-12); REQUIRE(cr.value() == Color::RED); REQUIRE(magic_enum::enum_cast(7).value() == Color::GREEN); REQUIRE(magic_enum::enum_cast(15).value() == Color::BLUE); REQUIRE_FALSE(magic_enum::enum_cast(0).has_value()); constexpr auto no = magic_enum::enum_cast(10); REQUIRE(no.value() == Numbers::one); REQUIRE(magic_enum::enum_cast(20).value() == Numbers::two); REQUIRE(magic_enum::enum_cast(30).value() == Numbers::three); REQUIRE_FALSE(magic_enum::enum_cast(0).has_value()); REQUIRE_FALSE(magic_enum::enum_cast(127).has_value()); constexpr auto dr = magic_enum::enum_cast(120); REQUIRE(magic_enum::enum_cast(85).value() == Directions::Up); REQUIRE(magic_enum::enum_cast(-42).value() == Directions::Down); REQUIRE(dr.value() == Directions::Right); REQUIRE(magic_enum::enum_cast(-120).value() == Directions::Left); REQUIRE_FALSE(magic_enum::enum_cast(0).has_value());; constexpr auto nt = magic_enum::enum_cast(300); REQUIRE(magic_enum::enum_cast(100).value() == number::one); REQUIRE(magic_enum::enum_cast(200).value() == number::two); REQUIRE(nt.value() == number::three); REQUIRE_FALSE(magic_enum::enum_cast(0).has_value()); REQUIRE_FALSE(magic_enum::enum_cast(0).has_value()); REQUIRE_FALSE(magic_enum::enum_cast(400).has_value()); } } TEST_CASE("enum_value") { constexpr auto cr = magic_enum::enum_value(0); REQUIRE(cr == Color::RED); REQUIRE(magic_enum::enum_value(1) == Color::GREEN); REQUIRE(magic_enum::enum_value(2) == Color::BLUE); constexpr auto no = magic_enum::enum_value(0); REQUIRE(no == Numbers::one); REQUIRE(magic_enum::enum_value(1) == Numbers::two); REQUIRE(magic_enum::enum_value(2) == Numbers::three); constexpr auto dr = magic_enum::enum_value(3); REQUIRE(magic_enum::enum_value(0) == Directions::Left); REQUIRE(magic_enum::enum_value(1) == Directions::Down); REQUIRE(magic_enum::enum_value(2) == Directions::Up); REQUIRE(dr == Directions::Right); constexpr auto nt = magic_enum::enum_value(2); REQUIRE(magic_enum::enum_value(0) == number::one); REQUIRE(magic_enum::enum_value(1) == number::two); REQUIRE(nt == number::three); } TEST_CASE("enum_values") { constexpr auto s1 = magic_enum::enum_values(); REQUIRE(s1 == std::array{{Color::RED, Color::GREEN, Color::BLUE}}); constexpr auto s2 = magic_enum::enum_values(); REQUIRE(s2 == std::array{{Numbers::one, Numbers::two, Numbers::three}}); constexpr auto s3 = magic_enum::enum_values(); REQUIRE(s3 == std::array{{Directions::Left, Directions::Down, Directions::Up, Directions::Right}}); constexpr auto s4 = magic_enum::enum_values(); REQUIRE(s4 == std::array{{number::one, number::two, number::three}}); } TEST_CASE("enum_count") { constexpr auto s1 = magic_enum::enum_count(); REQUIRE(s1 == 3); constexpr auto s2 = magic_enum::enum_count(); REQUIRE(s2 == 3); constexpr auto s3 = magic_enum::enum_count(); REQUIRE(s3 == 4); constexpr auto s4 = magic_enum::enum_count(); REQUIRE(s4 == 3); } TEST_CASE("enum_name") { constexpr Color cr = Color::RED; constexpr auto cr_name = magic_enum::enum_name(cr); Color cm[3] = {Color::RED, Color::GREEN, Color::BLUE}; REQUIRE(cr_name.value() == "RED"); REQUIRE(magic_enum::enum_name(Color::BLUE).value() == "BLUE"); REQUIRE(magic_enum::enum_name(cm[1]).value() == "GREEN"); REQUIRE_FALSE(magic_enum::enum_name(static_cast(0)).has_value()); constexpr Numbers no = Numbers::one; constexpr auto no_name = magic_enum::enum_name(no); REQUIRE(no_name.value() == "one"); REQUIRE(magic_enum::enum_name(Numbers::two).value() == "two"); REQUIRE(magic_enum::enum_name(Numbers::three).value() == "three"); REQUIRE_FALSE(magic_enum::enum_name(static_cast(0)).has_value()); REQUIRE_FALSE(magic_enum::enum_name(static_cast(127)).has_value()); constexpr Directions dr = Directions::Right; constexpr auto dr_name = magic_enum::enum_name(dr); REQUIRE(magic_enum::enum_name(Directions::Up).value() == "Up"); REQUIRE(magic_enum::enum_name(Directions::Down).value() == "Down"); REQUIRE(dr_name.value() == "Right"); REQUIRE(magic_enum::enum_name(Directions::Left).value() == "Left"); REQUIRE_FALSE(magic_enum::enum_name(static_cast(0)).has_value()); constexpr number nt = number::three; constexpr auto nt_name = magic_enum::enum_name(nt); REQUIRE(magic_enum::enum_name(number::one).value() == "one"); REQUIRE(magic_enum::enum_name(number::two).value() == "two"); REQUIRE(nt_name.value() == "three"); REQUIRE_FALSE(magic_enum::enum_name(static_cast(0)).has_value()); REQUIRE_FALSE(magic_enum::enum_name(static_cast(400)).has_value()); } TEST_CASE("enum_names") { constexpr auto s1 = magic_enum::enum_names(); REQUIRE(s1 == std::array{{"RED", "GREEN", "BLUE"}}); constexpr auto s2 = magic_enum::enum_names(); REQUIRE(s2 == std::array{{"one", "two", "three"}}); constexpr auto s3 = magic_enum::enum_names(); REQUIRE(s3 == std::array{{"Left", "Down", "Up", "Right"}}); constexpr auto s4 = magic_enum::enum_names(); REQUIRE(s4 == std::array{{"one", "two", "three"}}); } TEST_CASE("operator<<") { auto test_ostream = [](auto e, std::string_view name) { using namespace magic_enum::ops; std::stringstream ss; ss << e; REQUIRE(ss.str() == name); }; test_ostream(Color::RED, "RED"); test_ostream(Color::GREEN, "GREEN"); test_ostream(Color::BLUE, "BLUE"); test_ostream(static_cast(0), ""); test_ostream(Numbers::one, "one"); test_ostream(Numbers::two, "two"); test_ostream(Numbers::three, "three"); test_ostream(static_cast(0), ""); test_ostream(static_cast(127), ""); test_ostream(Directions::Up, "Up"); test_ostream(Directions::Down, "Down"); test_ostream(Directions::Right, "Right"); test_ostream(Directions::Left, "Left"); test_ostream(static_cast(0), ""); test_ostream(number::one, "one"); test_ostream(number::two, "two"); test_ostream(number::three, "three"); test_ostream(static_cast(0), ""); test_ostream(static_cast(400), ""); } TEST_CASE("type_traits") { REQUIRE_FALSE(magic_enum::is_unscoped_enum_v); REQUIRE_FALSE(magic_enum::is_unscoped_enum_v); REQUIRE(magic_enum::is_unscoped_enum_v); REQUIRE(magic_enum::is_unscoped_enum_v); REQUIRE(magic_enum::is_scoped_enum_v); REQUIRE(magic_enum::is_scoped_enum_v); REQUIRE_FALSE(magic_enum::is_scoped_enum_v); REQUIRE_FALSE(magic_enum::is_scoped_enum_v); }