// Licensed under the MIT License . // SPDX-License-Identifier: MIT // Copyright (c) 2019 - 2024 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 #undef MAGIC_ENUM_RANGE_MIN #define MAGIC_ENUM_RANGE_MIN -120 #undef MAGIC_ENUM_RANGE_MAX #define MAGIC_ENUM_RANGE_MAX 120 #include #include #include #include #include #include #include enum class Language : int { 日本語 = 10, 한국어 = 20, English = 30, 😃 = 40, TVÅ = 50 }; enum class LanguageFlag : int { 日本語 = 1 << 1, 한국어 = 1 << 2, English = 1 << 3, 😃 = 1 << 4 }; using namespace magic_enum; static_assert(is_magic_enum_supported, "magic_enum: Unsupported compiler (https://github.com/Neargye/magic_enum#compiler-compatibility)."); TEST_CASE("enum_cast") { SECTION("string") { constexpr auto lang = enum_cast("日本語"); REQUIRE(enum_cast("한국어").value() == Language::한국어); REQUIRE(enum_cast("English").value() == Language::English); REQUIRE(lang.value() == Language::日本語); REQUIRE(enum_cast("😃").value() == Language::😃); REQUIRE(enum_cast("TVÅ").value() == Language::TVÅ); REQUIRE_FALSE(enum_cast("Französisch").has_value()); } SECTION("integer") { constexpr auto lang = enum_cast(10); REQUIRE(enum_cast(20).value() == Language::한국어); REQUIRE(enum_cast(30).value() == Language::English); REQUIRE(lang.value() == Language::日本語); REQUIRE(enum_cast(40).value() == Language::😃); REQUIRE_FALSE(enum_cast(0).has_value()); } } TEST_CASE("enum_integer") { constexpr auto lang = enum_integer(Language::日本語); Language korean = Language::한국어; REQUIRE(enum_integer(korean) == 20); REQUIRE(enum_integer(Language::English) == 30); REQUIRE(enum_integer(Language::😃) == 40); REQUIRE(lang == 10); REQUIRE(enum_integer(static_cast(0)) == 0); } TEST_CASE("enum_index") { constexpr auto lang = enum_index(Language::日本語); Language korean = Language::한국어; REQUIRE(enum_index(korean) == 1); REQUIRE(enum_index(Language::English).value() == 2); REQUIRE(enum_index(Language::😃) == 3); REQUIRE(lang.value() == 0); REQUIRE_FALSE(enum_index(static_cast(0)).has_value()); } TEST_CASE("enum_contains") { SECTION("value") { constexpr auto lang = enum_contains(Language::日本語); Language korean = Language::한국어; REQUIRE(enum_contains(korean)); REQUIRE(enum_contains(Language::English)); REQUIRE(enum_contains(Language::😃)); REQUIRE(lang); } SECTION("integer") { constexpr auto lang = enum_integer(Language::日本語); REQUIRE(enum_contains(lang)); REQUIRE(enum_contains(Language::한국어)); REQUIRE(enum_contains(Language::😃)); REQUIRE_FALSE(enum_contains(static_cast(0))); } SECTION("string") { auto lang = std::string{"日本語"}; REQUIRE(enum_contains("한국어")); REQUIRE(enum_contains("English")); REQUIRE(enum_contains(lang)); REQUIRE(enum_contains("😃")); REQUIRE_FALSE(enum_contains("None")); } } TEST_CASE("enum_value") { constexpr auto lang = enum_value(3); REQUIRE(enum_value(0) == Language::日本語); REQUIRE(enum_value(1) == Language::한국어); REQUIRE(enum_value(2) == Language::English); REQUIRE(lang == Language::😃); } TEST_CASE("enum_values") { constexpr auto& s7 = enum_values(); REQUIRE(s7 == std::array{{Language::日本語, Language::한국어, Language::English, Language::😃, Language::TVÅ}}); } TEST_CASE("enum_count") { constexpr auto s7 = enum_count(); REQUIRE(s7 == 5); } TEST_CASE("enum_name") { SECTION("automatic storage") { constexpr Language lang = Language::日本語; constexpr auto lang_name = enum_name(lang); Language lk = Language::한국어; REQUIRE(enum_name(lk) == "한국어"); REQUIRE(enum_name(Language::English) == "English"); REQUIRE(lang_name == "日本語"); REQUIRE(enum_name(Language::😃) == "😃"); REQUIRE(enum_name(Language::TVÅ) == "TVÅ"); REQUIRE(enum_name(static_cast(0)).empty()); } SECTION("static storage") { constexpr Language lang = Language::日本語; constexpr auto lang_name = enum_name(); REQUIRE(enum_name() == "한국어"); REQUIRE(enum_name() == "English"); REQUIRE(lang_name == "日本語"); REQUIRE(enum_name() == "😃"); } } TEST_CASE("enum_names") { constexpr auto& s5 = enum_names(); REQUIRE(s5 == std::array{{"日本語", "한국어", "English", "😃", "TVÅ"}}); } TEST_CASE("enum_entries") { constexpr auto& s5 = enum_entries(); REQUIRE(s5 == std::array, 5>{{{Language::日本語, "日本語"}, {Language::한국어, "한국어"}, {Language::English, "English"}, {Language::😃, "😃"}, {Language::TVÅ, "TVÅ"}}}); } TEST_CASE("ostream_operators") { auto test_ostream = [](auto e, std::string name) { using namespace magic_enum::ostream_operators; std::stringstream ss; ss << e; REQUIRE(ss); REQUIRE(ss.str() == name); }; test_ostream(std::make_optional(Language::日本語), "日本語"); test_ostream(Language::한국어, "한국어"); test_ostream(Language::English, "English"); test_ostream(Language::😃, "😃"); test_ostream(static_cast(0), "0"); test_ostream(std::make_optional(static_cast(0)), "0"); } TEST_CASE("istream_operators") { auto test_istream = [](const auto e, std::string name) { using namespace magic_enum::istream_operators; std::istringstream ss(name); std::decay_t v; ss >> v; REQUIRE(ss); REQUIRE(v == e); }; test_istream(Language::한국어, "한국어"); test_istream(Language::English, "English"); test_istream(Language::😃, "😃"); } TEST_CASE("bitwise_operators") { using namespace magic_enum::bitwise_operators; SECTION("operator^") { REQUIRE(enum_integer(~Language::日本語) == ~enum_integer(Language::日本語)); } SECTION("operator|") { REQUIRE(enum_integer(Language::日本語 | Language::한국어) == (enum_integer(Language::日本語) | enum_integer(Language::한국어))); } SECTION("operator&") { REQUIRE(enum_integer(Language::日本語 & Language::한국어) == (enum_integer(Language::日本語) & enum_integer(Language::한국어))); } SECTION("operator^") { REQUIRE(enum_integer(Language::日本語 ^ Language::한국어) == (enum_integer(Language::日本語) ^ enum_integer(Language::한국어))); } SECTION("operator|=") { Language x5 = Language::日本語; x5 |= Language::한국어; REQUIRE(enum_integer(x5) == (enum_integer(Language::日本語) | enum_integer(Language::한국어))); } SECTION("operator&=") { Language x5 = Language::日本語; x5 &= Language::한국어; REQUIRE(enum_integer(x5) == (enum_integer(Language::日本語) & enum_integer(Language::한국어))); } SECTION("operator^=") { Language x5 = Language::日本語; x5 ^= Language::한국어; REQUIRE(enum_integer(x5) == (enum_integer(Language::日本語) ^ enum_integer(Language::한국어))); } } TEST_CASE("type_traits") { REQUIRE_FALSE(is_unscoped_enum_v); } TEST_CASE("enum_type_name") { REQUIRE(enum_type_name() == "Language"); } TEST_CASE("extrema") { SECTION("min") { REQUIRE(magic_enum::customize::enum_range::min == MAGIC_ENUM_RANGE_MIN); REQUIRE(magic_enum::detail::reflected_min>() == MAGIC_ENUM_RANGE_MIN); REQUIRE(magic_enum::detail::min_v> == 10); } SECTION("max") { REQUIRE(magic_enum::customize::enum_range::max == MAGIC_ENUM_RANGE_MAX); REQUIRE(magic_enum::detail::reflected_max>() == MAGIC_ENUM_RANGE_MAX); REQUIRE(magic_enum::detail::max_v> == 50); } } /* LanguageFlag tests */ TEST_CASE("flag enum_cast") { SECTION("string") { constexpr auto lang = enum_cast("日本語"); REQUIRE(enum_cast("한국어").value() == LanguageFlag::한국어); REQUIRE(enum_cast("English").value() == LanguageFlag::English); REQUIRE(lang.value() == LanguageFlag::日本語); REQUIRE(enum_cast("😃").value() == LanguageFlag::😃); REQUIRE_FALSE(enum_cast("None").has_value()); } SECTION("integer") { constexpr auto lang = enum_cast(1 << 1); REQUIRE(enum_cast(1 << 2).value() == LanguageFlag::한국어); REQUIRE(enum_cast(1 << 3).value() == LanguageFlag::English); REQUIRE(lang.value() == LanguageFlag::日本語); REQUIRE(enum_cast(1 << 4).value() == LanguageFlag::😃); REQUIRE_FALSE(enum_cast(0).has_value()); } } TEST_CASE("flag enum_index") { constexpr auto lang = enum_index(LanguageFlag::日本語); LanguageFlag korean = LanguageFlag::한국어; REQUIRE(enum_index(korean).value() == 1); REQUIRE(enum_index(LanguageFlag::English).value() == 2); REQUIRE(enum_index(LanguageFlag::😃).value() == 3); REQUIRE(lang.value() == 0); REQUIRE_FALSE(enum_index(static_cast(0)).has_value()); } TEST_CASE("flag enum_contains") { SECTION("value") { constexpr auto lang = enum_index(LanguageFlag::日本語); LanguageFlag korean = LanguageFlag::한국어; REQUIRE(enum_contains(korean)); REQUIRE(enum_contains(LanguageFlag::English)); REQUIRE(enum_contains(LanguageFlag::😃)); REQUIRE(lang); REQUIRE_FALSE(enum_contains(static_cast(0))); } SECTION("integer") { constexpr auto lang = enum_contains(1 << 1); REQUIRE(lang); REQUIRE(enum_contains(1 << 2)); REQUIRE(enum_contains(1 << 3)); REQUIRE(enum_contains(1 << 4)); REQUIRE_FALSE(enum_contains(static_cast(0))); } SECTION("string") { auto lang = std::string{"日本語"}; REQUIRE(enum_contains("한국어")); REQUIRE(enum_contains("English")); REQUIRE(enum_contains(lang)); REQUIRE(enum_contains("😃")); REQUIRE_FALSE(enum_contains("None")); } } TEST_CASE("flag enum_value") { constexpr auto lang = enum_value(3); REQUIRE(enum_value(0) == LanguageFlag::日本語); REQUIRE(enum_value(1) == LanguageFlag::한국어); REQUIRE(enum_value(2) == LanguageFlag::English); REQUIRE(lang == LanguageFlag::😃); } TEST_CASE("flag enum_values") { constexpr auto& s5 = enum_values(); REQUIRE(s5 == std::array{{LanguageFlag::日本語, LanguageFlag::한국어, LanguageFlag::English, LanguageFlag::😃}}); } TEST_CASE("flag enum_count") { constexpr auto s5 = enum_count(); REQUIRE(s5 == 4); } TEST_CASE("flag enum_name") { SECTION("automatic storage") { constexpr LanguageFlag lang = LanguageFlag::日本語; constexpr auto lang_name = enum_name(lang); LanguageFlag lk = LanguageFlag::한국어; REQUIRE(enum_name(lk) == "한국어"); REQUIRE(enum_name(LanguageFlag::English) == "English"); REQUIRE(lang_name == "日本語"); REQUIRE(enum_name(LanguageFlag::😃) == "😃"); REQUIRE(enum_name(static_cast(0)).empty()); } } TEST_CASE("flag enum_flags_name") { constexpr LanguageFlag lang = LanguageFlag::日本語; auto lang_name = enum_flags_name(lang); LanguageFlag lk = LanguageFlag::한국어; REQUIRE(enum_flags_name(lk) == "한국어"); REQUIRE(enum_flags_name(LanguageFlag::English) == "English"); REQUIRE(lang_name == "日本語"); REQUIRE(enum_flags_name(LanguageFlag::😃) == "😃"); REQUIRE(enum_flags_name(static_cast(0)).empty()); } TEST_CASE("flag enum_names") { constexpr auto& s5 = enum_names(); REQUIRE(s5 == std::array{{"日本語", "한국어", "English", "😃"}}); } TEST_CASE("flag enum_entries") { constexpr auto& s5 = enum_entries(); REQUIRE(s5 == std::array, 4>{{{LanguageFlag::日本語, "日本語"}, {LanguageFlag::한국어, "한국어"}, {LanguageFlag::English, "English"}, {LanguageFlag::😃, "😃"}}}); } TEST_CASE("flag ostream_operators") { auto test_ostream = [](auto e, std::string name) { using namespace magic_enum::ostream_operators; std::stringstream ss; ss << e; REQUIRE(ss.str() == name); }; test_ostream(std::make_optional(LanguageFlag::日本語), "日本語"); test_ostream(LanguageFlag::한국어, "한국어"); test_ostream(LanguageFlag::English, "English"); test_ostream(LanguageFlag::😃, "😃"); test_ostream(static_cast(0), "0"); test_ostream(std::make_optional(static_cast(0)), "0"); } TEST_CASE("flag istream_operators") { auto test_istream = [](const auto e, std::string name) { using namespace magic_enum::istream_operators; std::istringstream ss(name); std::decay_t v; ss >> v; REQUIRE(v == e); REQUIRE(ss); }; test_istream(LanguageFlag::한국어, "한국어"); test_istream(LanguageFlag::English, "English"); test_istream(LanguageFlag::😃, "😃"); } TEST_CASE("flag bitwise_operators") { using namespace magic_enum::bitwise_operators; SECTION("operator~") { REQUIRE(enum_integer(~LanguageFlag::日本語) == ~enum_integer(LanguageFlag::日本語)); } SECTION("operator|") { REQUIRE(enum_integer(LanguageFlag::日本語 | LanguageFlag::한국어) == (enum_integer(LanguageFlag::日本語) | enum_integer(LanguageFlag::한국어))); } SECTION("operator&") { REQUIRE(enum_integer(LanguageFlag::日本語 & LanguageFlag::한국어) == (enum_integer(LanguageFlag::日本語) & enum_integer(LanguageFlag::한국어))); } SECTION("operator^") { REQUIRE(enum_integer(LanguageFlag::日本語 ^ LanguageFlag::한국어) == (enum_integer(LanguageFlag::日本語) ^ enum_integer(LanguageFlag::한국어))); } SECTION("operator|=") { LanguageFlag x5 = LanguageFlag::日本語; x5 |= LanguageFlag::한국어; REQUIRE(enum_integer(x5) == (enum_integer(LanguageFlag::日本語) | enum_integer(LanguageFlag::한국어))); } SECTION("operator&=") { LanguageFlag x5 = LanguageFlag::日本語; x5 &= LanguageFlag::한국어; REQUIRE(enum_integer(x5) == (enum_integer(LanguageFlag::日本語) & enum_integer(LanguageFlag::한국어))); } SECTION("operator^=") { LanguageFlag x5 = LanguageFlag::日本語; x5 ^= LanguageFlag::한국어; REQUIRE(enum_integer(x5) == (enum_integer(LanguageFlag::日本語) ^ enum_integer(LanguageFlag::한국어))); } }