#include #include #include #include #include #include #include "../common/config.h" struct clazz { void setter(int v) { member = v; } int getter() const { return member; } static void static_setter(clazz &instance, int v) { instance.member = v; } static int static_getter(const clazz &instance) { return instance.member; } static void reset_value() { value = 0; } static int get_value() { return value; } static clazz factory(int v) { clazz instance{}; instance.member = v; return instance; } int member{}; const int cmember{}; inline static int value{}; inline static const int cvalue{}; inline static int arr[3u]{}; }; struct dummy {}; struct MetaUtility: ::testing::Test { void SetUp() override { clazz::value = 0; } }; using MetaUtilityDeathTest = MetaUtility; TEST_F(MetaUtility, MetaDispatch) { int value = 42; auto as_void = entt::meta_dispatch(value); auto as_ref = entt::meta_dispatch(value); auto as_cref = entt::meta_dispatch(value); auto as_is = entt::meta_dispatch(value); ASSERT_EQ(as_void.type(), entt::resolve()); ASSERT_EQ(as_ref.type(), entt::resolve()); ASSERT_EQ(as_cref.type(), entt::resolve()); ASSERT_EQ(as_is.type(), entt::resolve()); ASSERT_NE(as_is.try_cast(), nullptr); ASSERT_NE(as_ref.try_cast(), nullptr); ASSERT_EQ(as_cref.try_cast(), nullptr); ASSERT_NE(as_cref.try_cast(), nullptr); ASSERT_EQ(as_is.cast(), 42); ASSERT_EQ(as_ref.cast(), 42); ASSERT_EQ(as_cref.cast(), 42); } TEST_F(MetaUtility, MetaDispatchMetaAny) { entt::meta_any any{42}; auto from_any = entt::meta_dispatch(any); auto from_const_any = entt::meta_dispatch(std::as_const(any)); ASSERT_EQ(from_any.type(), entt::resolve()); ASSERT_EQ(from_const_any.type(), entt::resolve()); ASSERT_NE(from_any.try_cast(), nullptr); ASSERT_NE(from_const_any.try_cast(), nullptr); ASSERT_EQ(from_any.cast(), 42); ASSERT_EQ(from_const_any.cast(), 42); } TEST_F(MetaUtility, MetaDispatchMetaAnyAsRef) { entt::meta_any any{42}; auto from_any = entt::meta_dispatch(any.as_ref()); auto from_const_any = entt::meta_dispatch(std::as_const(any).as_ref()); ASSERT_EQ(from_any.type(), entt::resolve()); ASSERT_EQ(from_const_any.type(), entt::resolve()); ASSERT_NE(from_any.try_cast(), nullptr); ASSERT_EQ(from_const_any.try_cast(), nullptr); ASSERT_NE(from_const_any.try_cast(), nullptr); ASSERT_EQ(from_any.cast(), 42); ASSERT_EQ(from_const_any.cast(), 42); } TEST_F(MetaUtility, MetaArg) { ASSERT_EQ((entt::meta_arg>(0u)), entt::resolve()); ASSERT_EQ((entt::meta_arg>(1u)), entt::resolve()); } ENTT_DEBUG_TEST_F(MetaUtilityDeathTest, MetaArg) { ASSERT_DEATH([[maybe_unused]] auto type = entt::meta_arg>(0u), ""); ASSERT_DEATH([[maybe_unused]] auto type = entt::meta_arg>(3u), ""); } TEST_F(MetaUtility, MetaSetter) { const int invalid{}; clazz instance{}; ASSERT_FALSE((entt::meta_setter(instance, instance))); ASSERT_FALSE((entt::meta_setter(std::as_const(instance), 42))); ASSERT_FALSE((entt::meta_setter(invalid, 42))); ASSERT_TRUE((entt::meta_setter(instance, 42))); ASSERT_EQ(instance.member, 42); ASSERT_FALSE((entt::meta_setter(instance, instance))); ASSERT_FALSE((entt::meta_setter(std::as_const(instance), 3))); ASSERT_FALSE((entt::meta_setter(invalid, 3))); ASSERT_TRUE((entt::meta_setter(instance, 3))); ASSERT_EQ(instance.member, 3); ASSERT_FALSE((entt::meta_setter(instance, instance))); ASSERT_FALSE((entt::meta_setter(invalid, 99))); ASSERT_TRUE((entt::meta_setter(instance, 99))); ASSERT_EQ(instance.member, 99); ASSERT_FALSE((entt::meta_setter(instance, 99))); ASSERT_FALSE((entt::meta_setter(invalid, 99))); ASSERT_EQ(instance.cmember, 0); ASSERT_FALSE((entt::meta_setter(instance, instance))); ASSERT_TRUE((entt::meta_setter(invalid, 1))); ASSERT_TRUE((entt::meta_setter(instance, 2))); ASSERT_EQ(clazz::value, 2); ASSERT_FALSE((entt::meta_setter(instance, 1))); ASSERT_FALSE((entt::meta_setter(invalid, 1))); ASSERT_EQ(clazz::cvalue, 0); } TEST_F(MetaUtility, MetaGetter) { const int invalid{}; clazz instance{}; ASSERT_FALSE((entt::meta_getter(invalid))); ASSERT_EQ((entt::meta_getter(instance)).cast(), 0); ASSERT_FALSE((entt::meta_getter(invalid))); ASSERT_EQ((entt::meta_getter(instance)).cast(), 0); ASSERT_FALSE((entt::meta_getter(invalid))); ASSERT_EQ((entt::meta_getter(instance)).cast(), 0); ASSERT_EQ((entt::meta_getter(std::as_const(instance))).cast(), 0); ASSERT_FALSE((entt::meta_getter(invalid))); ASSERT_EQ((entt::meta_getter(instance)).cast(), 0); ASSERT_EQ((entt::meta_getter(std::as_const(instance))).cast(), 0); ASSERT_FALSE((entt::meta_getter(invalid))); ASSERT_FALSE((entt::meta_getter(instance))); ASSERT_EQ((entt::meta_getter(invalid)).cast(), 0); ASSERT_EQ((entt::meta_getter(instance)).cast(), 0); ASSERT_EQ((entt::meta_getter(invalid)).cast(), 0); ASSERT_EQ((entt::meta_getter(instance)).cast(), 0); ASSERT_EQ((entt::meta_getter(invalid)).cast(), 42); ASSERT_EQ((entt::meta_getter(instance)).cast(), 42); } TEST_F(MetaUtility, MetaInvokeWithCandidate) { entt::meta_any args[2u]{clazz{}, 42}; args[0u].cast().value = 99; ASSERT_FALSE((entt::meta_invoke({}, &clazz::setter, nullptr))); ASSERT_FALSE((entt::meta_invoke({}, &clazz::getter, nullptr))); ASSERT_TRUE((entt::meta_invoke(args[0u], &clazz::setter, args + 1u))); ASSERT_FALSE((entt::meta_invoke(args[0u], &clazz::setter, args))); ASSERT_EQ((entt::meta_invoke(args[0u], &clazz::getter, nullptr)).cast(), 42); ASSERT_FALSE((entt::meta_invoke(args[1u], &clazz::getter, nullptr))); ASSERT_EQ((entt::meta_invoke({}, &clazz::get_value, nullptr)).cast(), 99); ASSERT_TRUE((entt::meta_invoke({}, &clazz::reset_value, nullptr))); ASSERT_EQ(args[0u].cast().value, 0); const auto setter = [](int &value) { value = 3; }; const auto getter = [](int value) { return value * 2; }; ASSERT_TRUE(entt::meta_invoke({}, setter, args + 1u)); ASSERT_EQ(entt::meta_invoke({}, getter, args + 1u).cast(), 6); } TEST_F(MetaUtility, MetaInvoke) { entt::meta_any args[2u]{clazz{}, 42}; args[0u].cast().value = 99; ASSERT_FALSE((entt::meta_invoke({}, nullptr))); ASSERT_FALSE((entt::meta_invoke({}, nullptr))); ASSERT_TRUE((entt::meta_invoke(args[0u], args + 1u))); ASSERT_FALSE((entt::meta_invoke(args[0u], args))); ASSERT_EQ((entt::meta_invoke(args[0u], nullptr)).cast(), 42); ASSERT_FALSE((entt::meta_invoke(args[1u], nullptr))); ASSERT_EQ((entt::meta_invoke({}, nullptr)).cast(), 99); ASSERT_TRUE((entt::meta_invoke({}, nullptr))); ASSERT_EQ(args[0u].cast().value, 0); } TEST_F(MetaUtility, MetaConstructArgsOnly) { entt::meta_any args[2u]{clazz{}, 42}; const auto any = entt::meta_construct(args + 1u); ASSERT_TRUE(any); ASSERT_FALSE((entt::meta_construct(args))); ASSERT_EQ(any.cast().member, 42); } TEST_F(MetaUtility, MetaConstructWithCandidate) { entt::meta_any args[2u]{clazz{}, 42}; const auto any = entt::meta_construct(&clazz::factory, args + 1u); ASSERT_TRUE(any); ASSERT_FALSE((entt::meta_construct(&clazz::factory, args))); ASSERT_EQ(any.cast().member, 42); ASSERT_EQ(args[0u].cast().member, 0); ASSERT_TRUE((entt::meta_construct(&clazz::static_setter, args))); ASSERT_EQ(args[0u].cast().member, 42); const auto setter = [](int &value) { value = 3; }; const auto builder = [](int value) { return value * 2; }; ASSERT_TRUE(entt::meta_construct(setter, args + 1u)); ASSERT_EQ(entt::meta_construct(builder, args + 1u).cast(), 6); } TEST_F(MetaUtility, MetaConstruct) { entt::meta_any args[2u]{clazz{}, 42}; const auto any = entt::meta_construct(args + 1u); ASSERT_TRUE(any); ASSERT_FALSE((entt::meta_construct(args))); ASSERT_EQ(any.cast().member, 42); ASSERT_EQ(args[0u].cast().member, 0); ASSERT_TRUE((entt::meta_construct(args))); ASSERT_EQ(args[0u].cast().member, 42); }