| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463 |
- #include <array>
- #include <iterator>
- #include <string>
- #include <utility>
- #include <gtest/gtest.h>
- #include <entt/core/type_info.hpp>
- #include <entt/meta/context.hpp>
- #include <entt/meta/factory.hpp>
- #include <entt/meta/meta.hpp>
- #include <entt/meta/range.hpp>
- #include <entt/meta/resolve.hpp>
- #include "../../common/boxed_type.h"
- #include "../../common/config.h"
- #include "../../common/meta_traits.h"
- struct base {
- char member{};
- };
- struct clazz: base {
- clazz(int val)
- : value{val} {}
- explicit operator int() const noexcept {
- return get_int();
- }
- void set_int(int val) noexcept {
- value = val;
- }
- void set_boxed_int(test::boxed_int val) noexcept {
- value = val.value;
- }
- int get_int() const noexcept {
- return value;
- }
- static std::string to_string(const clazz &instance) {
- return std::to_string(instance.get_int());
- }
- static clazz from_string(const std::string &value) {
- return clazz{std::stoi(value)};
- }
- private:
- int value{};
- };
- struct dtor_callback {
- dtor_callback(bool &ref)
- : cb{&ref} {}
- static void on_destroy(dtor_callback &instance) {
- *instance.cb = !*instance.cb;
- }
- private:
- bool *cb;
- };
- struct MetaFactory: ::testing::Test {
- void TearDown() override {
- entt::meta_reset();
- }
- };
- using MetaFactoryDeathTest = MetaFactory;
- TEST_F(MetaFactory, Constructors) {
- entt::meta_ctx ctx{};
- ASSERT_EQ(entt::resolve(entt::type_id<int>()), entt::meta_type{});
- ASSERT_EQ(entt::resolve(ctx, entt::type_id<int>()), entt::meta_type{});
- entt::meta_factory<int> factory{};
- ASSERT_NE(entt::resolve(entt::type_id<int>()), entt::meta_type{});
- ASSERT_EQ(entt::resolve(ctx, entt::type_id<int>()), entt::meta_type{});
- // this is because of entt::meta, which should be deprecated nowadays
- ASSERT_FALSE(entt::resolve(entt::type_id<int>()).is_integral());
- factory = entt::meta_factory<int>{ctx};
- ASSERT_NE(entt::resolve(entt::type_id<int>()), entt::meta_type{});
- ASSERT_NE(entt::resolve(ctx, entt::type_id<int>()), entt::meta_type{});
- // this is because of entt::meta, which should be deprecated nowadays
- ASSERT_FALSE(entt::resolve(ctx, entt::type_id<int>()).is_integral());
- }
- TEST_F(MetaFactory, Type) {
- using namespace entt::literals;
- auto factory = entt::meta<int>();
- ASSERT_EQ(entt::resolve("foo"_hs), entt::meta_type{});
- factory.type("foo"_hs);
- ASSERT_NE(entt::resolve("foo"_hs), entt::meta_type{});
- ASSERT_EQ(entt::resolve<int>().id(), "foo"_hs);
- factory.type("bar"_hs);
- ASSERT_EQ(entt::resolve("foo"_hs), entt::meta_type{});
- ASSERT_NE(entt::resolve("bar"_hs), entt::meta_type{});
- ASSERT_EQ(entt::resolve<int>().id(), "bar"_hs);
- }
- ENTT_DEBUG_TEST_F(MetaFactoryDeathTest, Type) {
- using namespace entt::literals;
- auto factory = entt::meta<int>();
- auto other = entt::meta<double>();
- factory.type("foo"_hs);
- ASSERT_DEATH(other.type("foo"_hs);, "");
- }
- TEST_F(MetaFactory, Base) {
- auto factory = entt::meta<clazz>();
- decltype(std::declval<entt::meta_type>().base()) range{};
- ASSERT_NE(entt::resolve(entt::type_id<clazz>()), entt::meta_type{});
- ASSERT_EQ(entt::resolve(entt::type_id<base>()), entt::meta_type{});
- range = entt::resolve<clazz>().base();
- ASSERT_EQ(range.begin(), range.end());
- factory.base<base>();
- range = entt::resolve<clazz>().base();
- ASSERT_EQ(entt::resolve(entt::type_id<base>()), entt::meta_type{});
- ASSERT_NE(range.begin(), range.end());
- ASSERT_EQ(std::distance(range.begin(), range.end()), 1);
- ASSERT_EQ(range.begin()->first, entt::type_id<base>().hash());
- ASSERT_EQ(range.begin()->second.info(), entt::type_id<base>());
- }
- TEST_F(MetaFactory, Conv) {
- const clazz instance{3};
- auto factory = entt::meta<clazz>();
- const entt::meta_any any = entt::forward_as_meta(instance);
- ASSERT_FALSE(any.allow_cast<int>());
- ASSERT_FALSE(any.allow_cast<std::string>());
- factory.conv<int>().conv<&clazz::to_string>();
- ASSERT_TRUE(any.allow_cast<int>());
- ASSERT_TRUE(any.allow_cast<std::string>());
- ASSERT_EQ(any.allow_cast<int>().cast<int>(), instance.get_int());
- ASSERT_EQ(any.allow_cast<std::string>().cast<std::string>(), clazz::to_string(instance));
- }
- TEST_F(MetaFactory, Ctor) {
- const std::array values{1, 3};
- auto factory = entt::meta<clazz>();
- ASSERT_FALSE(entt::resolve<clazz>().construct(values[0u]));
- ASSERT_FALSE(entt::resolve<clazz>().construct(std::to_string(values[1u])));
- factory.ctor<int>().ctor<&clazz::from_string>();
- const auto instance = entt::resolve<clazz>().construct(values[0u]);
- const auto other = entt::resolve<clazz>().construct(std::to_string(values[1u]));
- ASSERT_TRUE(instance);
- ASSERT_TRUE(other);
- ASSERT_TRUE(instance.allow_cast<clazz>());
- ASSERT_TRUE(other.allow_cast<clazz>());
- ASSERT_EQ(instance.cast<const clazz &>().get_int(), values[0u]);
- ASSERT_EQ(other.cast<const clazz &>().get_int(), values[1u]);
- }
- TEST_F(MetaFactory, Dtor) {
- bool check = false;
- auto factory = entt::meta<dtor_callback>();
- entt::meta_any any{std::in_place_type<dtor_callback>, check};
- any.reset();
- ASSERT_FALSE(check);
- factory.dtor<&dtor_callback::on_destroy>();
- any.emplace<dtor_callback>(check);
- any.reset();
- ASSERT_TRUE(check);
- }
- TEST_F(MetaFactory, DataMemberObject) {
- using namespace entt::literals;
- base instance{'c'};
- auto factory = entt::meta<base>();
- entt::meta_type type = entt::resolve<base>();
- ASSERT_FALSE(type.data("member"_hs));
- factory.data<&base::member>("member"_hs);
- type = entt::resolve<base>();
- ASSERT_TRUE(type.data("member"_hs));
- ASSERT_EQ(type.get("member"_hs, std::as_const(instance)), instance.member);
- ASSERT_EQ(type.get("member"_hs, instance), instance.member);
- ASSERT_FALSE(type.set("member"_hs, std::as_const(instance), instance.member));
- ASSERT_TRUE(type.set("member"_hs, instance, instance.member));
- }
- TEST_F(MetaFactory, DataPointer) {
- using namespace entt::literals;
- auto factory = entt::meta<int>();
- entt::meta_type type = entt::resolve<int>();
- ASSERT_FALSE(type.data("value"_hs));
- static int value = 1;
- factory.data<&value>("value"_hs);
- type = entt::resolve<int>();
- ASSERT_TRUE(type.data("value"_hs));
- ASSERT_EQ(type.get("value"_hs, {}), value);
- ASSERT_TRUE(type.set("value"_hs, {}, value));
- }
- TEST_F(MetaFactory, DataValue) {
- using namespace entt::literals;
- constexpr int value = 1;
- auto factory = entt::meta<int>();
- entt::meta_type type = entt::resolve<int>();
- ASSERT_FALSE(type.data("value"_hs));
- factory.data<value>("value"_hs);
- type = entt::resolve<int>();
- ASSERT_TRUE(type.data("value"_hs));
- ASSERT_EQ(type.get("value"_hs, {}), value);
- ASSERT_FALSE(type.set("value"_hs, {}, value));
- }
- TEST_F(MetaFactory, DataGetterOnly) {
- using namespace entt::literals;
- clazz instance{1};
- auto factory = entt::meta<clazz>();
- entt::meta_type type = entt::resolve<clazz>();
- ASSERT_FALSE(type.data("value"_hs));
- factory.data<nullptr, &clazz::get_int>("value"_hs);
- type = entt::resolve<clazz>();
- ASSERT_TRUE(type.data("value"_hs));
- ASSERT_EQ(type.get("value"_hs, std::as_const(instance)), instance.get_int());
- ASSERT_EQ(type.get("value"_hs, instance), instance.get_int());
- ASSERT_FALSE(type.set("value"_hs, std::as_const(instance), instance.get_int()));
- ASSERT_FALSE(type.set("value"_hs, instance, instance.get_int()));
- }
- TEST_F(MetaFactory, DataSetterGetter) {
- using namespace entt::literals;
- clazz instance{1};
- auto factory = entt::meta<clazz>();
- entt::meta_type type = entt::resolve<clazz>();
- ASSERT_FALSE(type.data("value"_hs));
- factory.data<&clazz::set_int, &clazz::get_int>("value"_hs);
- type = entt::resolve<clazz>();
- ASSERT_TRUE(type.data("value"_hs));
- ASSERT_EQ(type.get("value"_hs, std::as_const(instance)), instance.get_int());
- ASSERT_EQ(type.get("value"_hs, instance), instance.get_int());
- ASSERT_FALSE(type.set("value"_hs, std::as_const(instance), instance.get_int()));
- ASSERT_TRUE(type.set("value"_hs, instance, instance.get_int()));
- }
- TEST_F(MetaFactory, DataMultiSetterGetter) {
- using namespace entt::literals;
- clazz instance{1};
- auto factory = entt::meta<clazz>();
- entt::meta_type type = entt::resolve<clazz>();
- ASSERT_FALSE(type.data("value"_hs));
- factory.data<entt::value_list<&clazz::set_int, &clazz::set_boxed_int>, &clazz::get_int>("value"_hs);
- type = entt::resolve<clazz>();
- ASSERT_TRUE(type.data("value"_hs));
- ASSERT_EQ(type.get("value"_hs, std::as_const(instance)), instance.get_int());
- ASSERT_EQ(type.get("value"_hs, instance), instance.get_int());
- ASSERT_FALSE(type.set("value"_hs, std::as_const(instance), instance.get_int()));
- ASSERT_TRUE(type.set("value"_hs, instance, instance.get_int()));
- ASSERT_FALSE(type.set("value"_hs, std::as_const(instance), test::boxed_int{instance.get_int()}));
- ASSERT_TRUE(type.set("value"_hs, instance, test::boxed_int{instance.get_int()}));
- }
- TEST_F(MetaFactory, DataOverwrite) {
- using namespace entt::literals;
- auto factory = entt::meta<clazz>();
- entt::meta_type type = entt::resolve<clazz>();
- ASSERT_FALSE(type.data("value"_hs));
- factory.data<nullptr, &clazz::get_int>("value"_hs);
- type = entt::resolve<clazz>();
- ASSERT_TRUE(type.data("value"_hs));
- ASSERT_TRUE(type.data("value"_hs).is_const());
- factory.data<&clazz::set_int, &clazz::get_int>("value"_hs);
- type = entt::resolve<clazz>();
- ASSERT_TRUE(type.data("value"_hs));
- ASSERT_FALSE(type.data("value"_hs).is_const());
- }
- TEST_F(MetaFactory, Func) {
- using namespace entt::literals;
- const clazz instance{1};
- auto factory = entt::meta<clazz>();
- entt::meta_type type = entt::resolve<clazz>();
- ASSERT_FALSE(type.func("func"_hs));
- factory.func<&clazz::get_int>("func"_hs);
- type = entt::resolve<clazz>();
- ASSERT_TRUE(type.func("func"_hs));
- ASSERT_TRUE(type.invoke("func"_hs, instance));
- ASSERT_EQ(type.invoke("func"_hs, instance).cast<int>(), instance.get_int());
- ASSERT_FALSE(type.invoke("func"_hs, {}));
- }
- TEST_F(MetaFactory, FuncOverload) {
- using namespace entt::literals;
- clazz instance{1};
- auto factory = entt::meta<clazz>();
- entt::meta_type type = entt::resolve<clazz>();
- ASSERT_FALSE(type.func("func"_hs));
- factory.func<&clazz::set_int>("func"_hs);
- ASSERT_TRUE(type.func("func"_hs));
- ASSERT_FALSE(type.func("func"_hs).next());
- factory.func<&clazz::set_boxed_int>("func"_hs);
- ASSERT_TRUE(type.func("func"_hs));
- ASSERT_TRUE(type.func("func"_hs).next());
- ASSERT_FALSE(type.func("func"_hs).next().next());
- ASSERT_TRUE(type.invoke("func"_hs, instance, 2));
- ASSERT_EQ(instance.get_int(), 2);
- ASSERT_TRUE(type.invoke("func"_hs, instance, test::boxed_int{3}));
- ASSERT_EQ(instance.get_int(), 3);
- }
- TEST_F(MetaFactory, Traits) {
- using namespace entt::literals;
- entt::meta<clazz>()
- .data<&base::member>("member"_hs)
- .func<&clazz::set_int>("func"_hs)
- .func<&clazz::set_boxed_int>("func"_hs);
- entt::meta_type type = entt::resolve<clazz>();
- ASSERT_EQ(type.traits<test::meta_traits>(), test::meta_traits::none);
- ASSERT_EQ(type.data("member"_hs).traits<test::meta_traits>(), test::meta_traits::none);
- ASSERT_EQ(type.func("func"_hs).traits<test::meta_traits>(), test::meta_traits::none);
- ASSERT_EQ(type.func("func"_hs).next().traits<test::meta_traits>(), test::meta_traits::none);
- entt::meta<clazz>()
- .traits(test::meta_traits::one | test::meta_traits::three)
- .data<&base::member>("member"_hs)
- .traits(test::meta_traits::one)
- .func<&clazz::set_int>("func"_hs)
- .traits(test::meta_traits::two)
- .func<&clazz::set_boxed_int>("func"_hs)
- .traits(test::meta_traits::three);
- // traits are copied and never refreshed
- type = entt::resolve<clazz>();
- ASSERT_EQ(type.traits<test::meta_traits>(), test::meta_traits::one | test::meta_traits::three);
- ASSERT_EQ(type.data("member"_hs).traits<test::meta_traits>(), test::meta_traits::one);
- ASSERT_EQ(type.func("func"_hs).traits<test::meta_traits>(), test::meta_traits::two);
- ASSERT_EQ(type.func("func"_hs).next().traits<test::meta_traits>(), test::meta_traits::three);
- }
- TEST_F(MetaFactory, Custom) {
- using namespace entt::literals;
- entt::meta<clazz>()
- .data<&base::member>("member"_hs)
- .func<&clazz::set_int>("func"_hs)
- .func<&clazz::set_boxed_int>("func"_hs);
- entt::meta_type type = entt::resolve<clazz>();
- ASSERT_EQ(static_cast<const int *>(type.custom()), nullptr);
- ASSERT_EQ(static_cast<const int *>(type.data("member"_hs).custom()), nullptr);
- ASSERT_EQ(static_cast<const int *>(type.func("func"_hs).custom()), nullptr);
- ASSERT_EQ(static_cast<const int *>(type.func("func"_hs).next().custom()), nullptr);
- entt::meta<clazz>()
- .custom<int>(0)
- .data<&base::member>("member"_hs)
- .custom<int>(1)
- .func<&clazz::set_int>("func"_hs)
- .custom<int>(2)
- .func<&clazz::set_boxed_int>("func"_hs)
- .custom<int>(3);
- // custom data pointers are copied and never refreshed
- type = entt::resolve<clazz>();
- ASSERT_EQ(static_cast<int>(type.custom()), 0);
- ASSERT_EQ(static_cast<int>(type.data("member"_hs).custom()), 1);
- ASSERT_EQ(static_cast<int>(type.func("func"_hs).custom()), 2);
- ASSERT_EQ(static_cast<int>(type.func("func"_hs).next().custom()), 3);
- }
- TEST_F(MetaFactory, Meta) {
- entt::meta_ctx ctx{};
- ASSERT_EQ(entt::resolve(entt::type_id<int>()), entt::meta_type{});
- ASSERT_EQ(entt::resolve(ctx, entt::type_id<int>()), entt::meta_type{});
- auto factory = entt::meta<int>();
- ASSERT_NE(entt::resolve(entt::type_id<int>()), entt::meta_type{});
- ASSERT_EQ(entt::resolve(ctx, entt::type_id<int>()), entt::meta_type{});
- ASSERT_TRUE(entt::resolve(entt::type_id<int>()).is_integral());
- factory = entt::meta_factory<int>{ctx};
- ASSERT_NE(entt::resolve(entt::type_id<int>()), entt::meta_type{});
- ASSERT_NE(entt::resolve(ctx, entt::type_id<int>()), entt::meta_type{});
- ASSERT_FALSE(entt::resolve(ctx, entt::type_id<int>()).is_integral());
- }
- TEST_F(MetaFactory, MetaReset) {
- // TODO
- }
|