1
0
Fork 0
mirror of https://github.com/Neargye/magic_enum.git synced 2026-01-08 23:24:20 +00:00
magic_enum/test/test_nonascii.cpp
2024-10-14 18:05:55 +03:00

445 lines
17 KiB
C++

// Licensed under the MIT License <http://opensource.org/licenses/MIT>.
// SPDX-License-Identifier: MIT
// Copyright (c) 2019 - 2024 Daniil Goncharov <neargye@gmail.com>.
//
// 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 <catch2/catch.hpp>
#undef MAGIC_ENUM_RANGE_MIN
#define MAGIC_ENUM_RANGE_MIN -120
#undef MAGIC_ENUM_RANGE_MAX
#define MAGIC_ENUM_RANGE_MAX 120
#include <magic_enum/magic_enum.hpp>
#include <magic_enum/magic_enum_fuse.hpp>
#include <magic_enum/magic_enum_iostream.hpp>
#include <array>
#include <cctype>
#include <string_view>
#include <sstream>
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<Language>("日本語");
REQUIRE(enum_cast<Language&>("한국어").value() == Language::);
REQUIRE(enum_cast<const Language>("English").value() == Language::English);
REQUIRE(lang.value() == Language::);
REQUIRE(enum_cast<Language>("😃").value() == Language::😃);
REQUIRE(enum_cast<Language>("TVÅ").value() == Language::TVÅ);
REQUIRE_FALSE(enum_cast<Language>("Französisch").has_value());
}
SECTION("integer") {
constexpr auto lang = enum_cast<Language>(10);
REQUIRE(enum_cast<Language&>(20).value() == Language::);
REQUIRE(enum_cast<const Language>(30).value() == Language::English);
REQUIRE(lang.value() == Language::);
REQUIRE(enum_cast<Language>(40).value() == Language::😃);
REQUIRE_FALSE(enum_cast<Language>(0).has_value());
}
}
TEST_CASE("enum_integer") {
constexpr auto lang = enum_integer(Language::);
Language korean = Language::;
REQUIRE(enum_integer<Language&>(korean) == 20);
REQUIRE(enum_integer<const Language>(Language::English) == 30);
REQUIRE(enum_integer(Language::😃) == 40);
REQUIRE(lang == 10);
REQUIRE(enum_integer(static_cast<Language>(0)) == 0);
}
TEST_CASE("enum_index") {
constexpr auto lang = enum_index<Language>(Language::);
Language korean = Language::;
REQUIRE(enum_index<Language&>(korean) == 1);
REQUIRE(enum_index<const Language>(Language::English).value() == 2);
REQUIRE(enum_index(Language::😃) == 3);
REQUIRE(lang.value() == 0);
REQUIRE_FALSE(enum_index(static_cast<Language>(0)).has_value());
}
TEST_CASE("enum_contains") {
SECTION("value") {
constexpr auto lang = enum_contains(Language::);
Language korean = Language::;
REQUIRE(enum_contains<Language&>(korean));
REQUIRE(enum_contains<const Language>(Language::English));
REQUIRE(enum_contains(Language::😃));
REQUIRE(lang);
}
SECTION("integer") {
constexpr auto lang = enum_integer(Language::);
REQUIRE(enum_contains<Language&>(lang));
REQUIRE(enum_contains<const Language>(Language::));
REQUIRE(enum_contains<Language>(Language::😃));
REQUIRE_FALSE(enum_contains<Language>(static_cast<Language>(0)));
}
SECTION("string") {
auto lang = std::string{"日本語"};
REQUIRE(enum_contains<Language&>("한국어"));
REQUIRE(enum_contains<Language>("English"));
REQUIRE(enum_contains<const Language>(lang));
REQUIRE(enum_contains<Language>("😃"));
REQUIRE_FALSE(enum_contains<Language>("None"));
}
}
TEST_CASE("enum_value") {
constexpr auto lang = enum_value<Language>(3);
REQUIRE(enum_value<Language&>(0) == Language::);
REQUIRE(enum_value<const Language>(1) == Language::);
REQUIRE(enum_value<Language>(2) == Language::English);
REQUIRE(lang == Language::😃);
}
TEST_CASE("enum_values") {
constexpr auto& s7 = enum_values<const Language>();
REQUIRE(s7 == std::array<Language, 5>{{Language::, Language::, Language::English, Language::😃, Language::TVÅ}});
}
TEST_CASE("enum_count") {
constexpr auto s7 = enum_count<Language>();
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<Language&>(lk) == "한국어");
REQUIRE(enum_name<const Language>(Language::English) == "English");
REQUIRE(lang_name == "日本語");
REQUIRE(enum_name(Language::😃) == "😃");
REQUIRE(enum_name(Language::TVÅ) == "TVÅ");
REQUIRE(enum_name(static_cast<Language>(0)).empty());
}
SECTION("static storage") {
constexpr Language lang = Language::;
constexpr auto lang_name = enum_name<lang>();
REQUIRE(enum_name<Language::>() == "한국어");
REQUIRE(enum_name<Language::English>() == "English");
REQUIRE(lang_name == "日本語");
REQUIRE(enum_name<Language::😃>() == "😃");
}
}
TEST_CASE("enum_names") {
constexpr auto& s5 = enum_names<const Language>();
REQUIRE(s5 == std::array<std::string_view, 5>{{"日本語", "한국어", "English", "😃", "TVÅ"}});
}
TEST_CASE("enum_entries") {
constexpr auto& s5 = enum_entries<const Language>();
REQUIRE(s5 == std::array<std::pair<Language, std::string_view>, 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<Language>(0), "0");
test_ostream(std::make_optional(static_cast<Language>(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<decltype(e)> 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<Language>);
}
TEST_CASE("enum_type_name") {
REQUIRE(enum_type_name<const Language&>() == "Language");
}
TEST_CASE("extrema") {
SECTION("min") {
REQUIRE(magic_enum::customize::enum_range<Language>::min == MAGIC_ENUM_RANGE_MIN);
REQUIRE(magic_enum::detail::reflected_min<Language, as_common<>>() == MAGIC_ENUM_RANGE_MIN);
REQUIRE(magic_enum::detail::min_v<Language, as_common<>> == 10);
}
SECTION("max") {
REQUIRE(magic_enum::customize::enum_range<Language>::max == MAGIC_ENUM_RANGE_MAX);
REQUIRE(magic_enum::detail::reflected_max<Language, as_common<>>() == MAGIC_ENUM_RANGE_MAX);
REQUIRE(magic_enum::detail::max_v<Language, as_common<>> == 50);
}
}
/* LanguageFlag tests */
TEST_CASE("flag enum_cast") {
SECTION("string") {
constexpr auto lang = enum_cast<LanguageFlag>("日本語");
REQUIRE(enum_cast<LanguageFlag&>("한국어").value() == LanguageFlag::);
REQUIRE(enum_cast<const LanguageFlag>("English").value() == LanguageFlag::English);
REQUIRE(lang.value() == LanguageFlag::);
REQUIRE(enum_cast<LanguageFlag>("😃").value() == LanguageFlag::😃);
REQUIRE_FALSE(enum_cast<LanguageFlag>("None").has_value());
}
SECTION("integer") {
constexpr auto lang = enum_cast<LanguageFlag>(1 << 1);
REQUIRE(enum_cast<LanguageFlag&>(1 << 2).value() == LanguageFlag::);
REQUIRE(enum_cast<const LanguageFlag>(1 << 3).value() == LanguageFlag::English);
REQUIRE(lang.value() == LanguageFlag::);
REQUIRE(enum_cast<LanguageFlag>(1 << 4).value() == LanguageFlag::😃);
REQUIRE_FALSE(enum_cast<LanguageFlag>(0).has_value());
}
}
TEST_CASE("flag enum_index") {
constexpr auto lang = enum_index<LanguageFlag>(LanguageFlag::);
LanguageFlag korean = LanguageFlag::;
REQUIRE(enum_index<LanguageFlag&>(korean).value() == 1);
REQUIRE(enum_index<const LanguageFlag>(LanguageFlag::English).value() == 2);
REQUIRE(enum_index(LanguageFlag::😃).value() == 3);
REQUIRE(lang.value() == 0);
REQUIRE_FALSE(enum_index(static_cast<LanguageFlag>(0)).has_value());
}
TEST_CASE("flag enum_contains") {
SECTION("value") {
constexpr auto lang = enum_index<LanguageFlag>(LanguageFlag::);
LanguageFlag korean = LanguageFlag::;
REQUIRE(enum_contains<LanguageFlag&>(korean));
REQUIRE(enum_contains<const LanguageFlag>(LanguageFlag::English));
REQUIRE(enum_contains(LanguageFlag::😃));
REQUIRE(lang);
REQUIRE_FALSE(enum_contains(static_cast<LanguageFlag>(0)));
}
SECTION("integer") {
constexpr auto lang = enum_contains<LanguageFlag&>(1 << 1);
REQUIRE(lang);
REQUIRE(enum_contains<const LanguageFlag>(1 << 2));
REQUIRE(enum_contains<LanguageFlag>(1 << 3));
REQUIRE(enum_contains<LanguageFlag>(1 << 4));
REQUIRE_FALSE(enum_contains(static_cast<LanguageFlag>(0)));
}
SECTION("string") {
auto lang = std::string{"日本語"};
REQUIRE(enum_contains<LanguageFlag&>("한국어"));
REQUIRE(enum_contains<LanguageFlag>("English"));
REQUIRE(enum_contains<const LanguageFlag>(lang));
REQUIRE(enum_contains<LanguageFlag>("😃"));
REQUIRE_FALSE(enum_contains<LanguageFlag>("None"));
}
}
TEST_CASE("flag enum_value") {
constexpr auto lang = enum_value<LanguageFlag>(3);
REQUIRE(enum_value<LanguageFlag&>(0) == LanguageFlag::);
REQUIRE(enum_value<const LanguageFlag>(1) == LanguageFlag::);
REQUIRE(enum_value<LanguageFlag>(2) == LanguageFlag::English);
REQUIRE(lang == LanguageFlag::😃);
}
TEST_CASE("flag enum_values") {
constexpr auto& s5 = enum_values<const LanguageFlag>();
REQUIRE(s5 == std::array<LanguageFlag, 4>{{LanguageFlag::, LanguageFlag::, LanguageFlag::English, LanguageFlag::😃}});
}
TEST_CASE("flag enum_count") {
constexpr auto s5 = enum_count<LanguageFlag>();
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<LanguageFlag&>(lk) == "한국어");
REQUIRE(enum_name<const LanguageFlag>(LanguageFlag::English) == "English");
REQUIRE(lang_name == "日本語");
REQUIRE(enum_name(LanguageFlag::😃) == "😃");
REQUIRE(enum_name(static_cast<LanguageFlag>(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<LanguageFlag&>(lk) == "한국어");
REQUIRE(enum_flags_name<const LanguageFlag>(LanguageFlag::English) == "English");
REQUIRE(lang_name == "日本語");
REQUIRE(enum_flags_name(LanguageFlag::😃) == "😃");
REQUIRE(enum_flags_name(static_cast<LanguageFlag>(0)).empty());
}
TEST_CASE("flag enum_names") {
constexpr auto& s5 = enum_names<const LanguageFlag>();
REQUIRE(s5 == std::array<std::string_view, 4>{{"日本語", "한국어", "English", "😃"}});
}
TEST_CASE("flag enum_entries") {
constexpr auto& s5 = enum_entries<const LanguageFlag>();
REQUIRE(s5 == std::array<std::pair<LanguageFlag, std::string_view>, 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<LanguageFlag>(0), "0");
test_ostream(std::make_optional(static_cast<LanguageFlag>(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<decltype(e)> 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::)));
}
}