meta_data.cpp 22 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730
  1. #include <cstdlib>
  2. #include <string>
  3. #include <utility>
  4. #include <gtest/gtest.h>
  5. #include <entt/core/hashed_string.hpp>
  6. #include <entt/core/type_traits.hpp>
  7. #include <entt/locator/locator.hpp>
  8. #include <entt/meta/context.hpp>
  9. #include <entt/meta/factory.hpp>
  10. #include <entt/meta/meta.hpp>
  11. #include <entt/meta/node.hpp>
  12. #include <entt/meta/policy.hpp>
  13. #include <entt/meta/range.hpp>
  14. #include <entt/meta/resolve.hpp>
  15. #include "../../common/config.h"
  16. #include "../../common/meta_traits.h"
  17. struct base {
  18. virtual ~base() = default;
  19. static void destroy(base &) {
  20. ++counter;
  21. }
  22. inline static int counter = 0; // NOLINT
  23. int value{3};
  24. };
  25. struct derived: base {
  26. derived() = default;
  27. };
  28. struct clazz {
  29. operator int() const {
  30. return h;
  31. }
  32. int i{0};
  33. const int j{1}; // NOLINT
  34. base instance{};
  35. inline static int h{2}; // NOLINT
  36. inline static const int k{3}; // NOLINT
  37. };
  38. struct setter_getter {
  39. int setter(double val) {
  40. return value = static_cast<int>(val);
  41. }
  42. int getter() const {
  43. return value;
  44. }
  45. int setter_with_ref(const int &val) {
  46. return value = val;
  47. }
  48. const int &getter_with_ref() const {
  49. return value;
  50. }
  51. static int static_setter(setter_getter &type, int value) {
  52. return type.value = value;
  53. }
  54. static int static_getter(const setter_getter &type) {
  55. return type.value;
  56. }
  57. int value{0};
  58. };
  59. struct multi_setter {
  60. void from_double(double val) {
  61. value = static_cast<int>(val);
  62. }
  63. void from_string(const char *val) {
  64. value = std::atoi(val);
  65. }
  66. int value{0};
  67. };
  68. struct array {
  69. inline static int global[2]; // NOLINT
  70. int local[4]; // NOLINT
  71. };
  72. enum class property_type : entt::id_type {
  73. random,
  74. value
  75. };
  76. struct MetaData: ::testing::Test {
  77. void SetUp() override {
  78. using namespace entt::literals;
  79. entt::meta<base>()
  80. .type("base"_hs)
  81. .dtor<base::destroy>()
  82. .data<&base::value>("value"_hs);
  83. entt::meta<derived>()
  84. .type("derived"_hs)
  85. .base<base>()
  86. .dtor<derived::destroy>()
  87. .data<&base::value>("value_from_base"_hs);
  88. entt::meta<clazz>()
  89. .type("clazz"_hs)
  90. .data<&clazz::i, entt::as_ref_t>("i"_hs)
  91. .custom<char>('c')
  92. .traits(test::meta_traits::one | test::meta_traits::two | test::meta_traits::three)
  93. .prop(3u, 0)
  94. .data<&clazz::i, entt::as_cref_t>("ci"_hs)
  95. .data<&clazz::j>("j"_hs)
  96. .traits(test::meta_traits::one)
  97. .prop("true"_hs, 1)
  98. .data<&clazz::h>("h"_hs)
  99. .traits(test::meta_traits::two)
  100. .prop(static_cast<entt::id_type>(property_type::random), 2)
  101. .data<&clazz::k>("k"_hs)
  102. .traits(test::meta_traits::three)
  103. .prop(static_cast<entt::id_type>(property_type::value), 3)
  104. .data<&clazz::instance>("base"_hs)
  105. .data<&clazz::i, entt::as_void_t>("void"_hs)
  106. .conv<int>();
  107. entt::meta<setter_getter>()
  108. .type("setter_getter"_hs)
  109. .data<&setter_getter::static_setter, &setter_getter::static_getter>("x"_hs)
  110. .data<&setter_getter::setter, &setter_getter::getter>("y"_hs)
  111. .data<&setter_getter::static_setter, &setter_getter::getter>("z"_hs)
  112. .data<&setter_getter::setter_with_ref, &setter_getter::getter_with_ref>("w"_hs)
  113. .data<nullptr, &setter_getter::getter>("z_ro"_hs)
  114. .data<nullptr, &setter_getter::value>("value"_hs);
  115. entt::meta<multi_setter>()
  116. .type("multi_setter"_hs)
  117. .data<entt::value_list<&multi_setter::from_double, &multi_setter::from_string>, &multi_setter::value>("value"_hs);
  118. entt::meta<array>()
  119. .type("array"_hs)
  120. .data<&array::global>("global"_hs)
  121. .data<&array::local>("local"_hs);
  122. base::counter = 0;
  123. }
  124. void TearDown() override {
  125. entt::meta_reset();
  126. }
  127. };
  128. using MetaDataDeathTest = MetaData;
  129. TEST_F(MetaData, Functionalities) {
  130. using namespace entt::literals;
  131. auto data = entt::resolve<clazz>().data("i"_hs);
  132. clazz instance{};
  133. ASSERT_TRUE(data);
  134. ASSERT_EQ(data, data);
  135. ASSERT_NE(data, entt::meta_data{});
  136. ASSERT_FALSE(data != data);
  137. ASSERT_TRUE(data == data);
  138. ASSERT_EQ(data.arity(), 1u);
  139. ASSERT_EQ(data.type(), entt::resolve<int>());
  140. ASSERT_EQ(data.arg(0u), entt::resolve<int>());
  141. ASSERT_FALSE(data.is_const());
  142. ASSERT_FALSE(data.is_static());
  143. ASSERT_EQ(data.get(instance).cast<int>(), 0);
  144. ASSERT_TRUE(data.set(instance, 1));
  145. ASSERT_EQ(data.get(instance).cast<int>(), 1);
  146. for(auto curr: data.prop()) {
  147. ASSERT_EQ(curr.first, 3u);
  148. ASSERT_EQ(curr.second.value(), 0);
  149. }
  150. ASSERT_FALSE(data.prop(2));
  151. ASSERT_FALSE(data.prop('c'));
  152. auto prop = data.prop(3u);
  153. ASSERT_TRUE(prop);
  154. ASSERT_EQ(prop.value(), 0);
  155. }
  156. TEST_F(MetaData, UserTraits) {
  157. using namespace entt::literals;
  158. ASSERT_EQ(entt::resolve<clazz>().data("ci"_hs).traits<test::meta_traits>(), test::meta_traits::none);
  159. ASSERT_EQ(entt::resolve<clazz>().data("base"_hs).traits<test::meta_traits>(), test::meta_traits::none);
  160. ASSERT_EQ(entt::resolve<clazz>().data("i"_hs).traits<test::meta_traits>(), test::meta_traits::one | test::meta_traits::two | test::meta_traits::three);
  161. ASSERT_EQ(entt::resolve<clazz>().data("j"_hs).traits<test::meta_traits>(), test::meta_traits::one);
  162. ASSERT_EQ(entt::resolve<clazz>().data("h"_hs).traits<test::meta_traits>(), test::meta_traits::two);
  163. ASSERT_EQ(entt::resolve<clazz>().data("k"_hs).traits<test::meta_traits>(), test::meta_traits::three);
  164. }
  165. ENTT_DEBUG_TEST_F(MetaDataDeathTest, UserTraits) {
  166. using namespace entt::literals;
  167. using traits_type = entt::internal::meta_traits;
  168. constexpr auto value = traits_type{static_cast<std::underlying_type_t<traits_type>>(traits_type::_user_defined_traits) + 1u};
  169. ASSERT_DEATH(entt::meta<clazz>().data<&clazz::i>("j"_hs).traits(value), "");
  170. }
  171. TEST_F(MetaData, Custom) {
  172. using namespace entt::literals;
  173. ASSERT_EQ(*static_cast<const char *>(entt::resolve<clazz>().data("i"_hs).custom()), 'c');
  174. ASSERT_EQ(static_cast<const char &>(entt::resolve<clazz>().data("i"_hs).custom()), 'c');
  175. ASSERT_EQ(static_cast<const int *>(entt::resolve<clazz>().data("i"_hs).custom()), nullptr);
  176. ASSERT_EQ(static_cast<const int *>(entt::resolve<clazz>().data("j"_hs).custom()), nullptr);
  177. }
  178. ENTT_DEBUG_TEST_F(MetaDataDeathTest, Custom) {
  179. using namespace entt::literals;
  180. ASSERT_DEATH([[maybe_unused]] int value = entt::resolve<clazz>().data("i"_hs).custom(), "");
  181. ASSERT_DEATH([[maybe_unused]] char value = entt::resolve<clazz>().data("j"_hs).custom(), "");
  182. }
  183. TEST_F(MetaData, Const) {
  184. using namespace entt::literals;
  185. auto data = entt::resolve<clazz>().data("j"_hs);
  186. clazz instance{};
  187. ASSERT_TRUE(data);
  188. ASSERT_EQ(data.arity(), 1u);
  189. ASSERT_EQ(data.type(), entt::resolve<int>());
  190. ASSERT_EQ(data.arg(0u), entt::resolve<int>());
  191. ASSERT_TRUE(data.is_const());
  192. ASSERT_FALSE(data.is_static());
  193. ASSERT_EQ(data.get(instance).cast<int>(), 1);
  194. ASSERT_FALSE(data.set(instance, 1));
  195. ASSERT_EQ(data.get(instance).cast<int>(), 1);
  196. for(auto curr: data.prop()) {
  197. ASSERT_EQ(curr.first, "true"_hs);
  198. ASSERT_EQ(curr.second.value(), 1);
  199. }
  200. ASSERT_FALSE(data.prop(false));
  201. ASSERT_FALSE(data.prop('c'));
  202. auto prop = data.prop("true"_hs);
  203. ASSERT_TRUE(prop);
  204. ASSERT_EQ(prop.value(), 1);
  205. }
  206. TEST_F(MetaData, Static) {
  207. using namespace entt::literals;
  208. auto data = entt::resolve<clazz>().data("h"_hs);
  209. ASSERT_TRUE(data);
  210. ASSERT_EQ(data.arity(), 1u);
  211. ASSERT_EQ(data.type(), entt::resolve<int>());
  212. ASSERT_EQ(data.arg(0u), entt::resolve<int>());
  213. ASSERT_FALSE(data.is_const());
  214. ASSERT_TRUE(data.is_static());
  215. ASSERT_EQ(data.get({}).cast<int>(), 2);
  216. ASSERT_TRUE(data.set({}, 1));
  217. ASSERT_EQ(data.get({}).cast<int>(), 1);
  218. for(auto curr: data.prop()) {
  219. ASSERT_EQ(curr.first, static_cast<entt::id_type>(property_type::random));
  220. ASSERT_EQ(curr.second.value(), 2);
  221. }
  222. ASSERT_FALSE(data.prop(static_cast<entt::id_type>(property_type::value)));
  223. ASSERT_FALSE(data.prop('c'));
  224. auto prop = data.prop(static_cast<entt::id_type>(property_type::random));
  225. ASSERT_TRUE(prop);
  226. ASSERT_EQ(prop.value(), 2);
  227. }
  228. TEST_F(MetaData, ConstStatic) {
  229. using namespace entt::literals;
  230. auto data = entt::resolve<clazz>().data("k"_hs);
  231. ASSERT_TRUE(data);
  232. ASSERT_EQ(data.arity(), 1u);
  233. ASSERT_EQ(data.type(), entt::resolve<int>());
  234. ASSERT_EQ(data.arg(0u), entt::resolve<int>());
  235. ASSERT_TRUE(data.is_const());
  236. ASSERT_TRUE(data.is_static());
  237. ASSERT_EQ(data.get({}).cast<int>(), 3);
  238. ASSERT_FALSE(data.set({}, 1));
  239. ASSERT_EQ(data.get({}).cast<int>(), 3);
  240. for(auto curr: data.prop()) {
  241. ASSERT_EQ(curr.first, static_cast<entt::id_type>(property_type::value));
  242. ASSERT_EQ(curr.second.value(), 3);
  243. }
  244. ASSERT_FALSE(data.prop(static_cast<entt::id_type>(property_type::random)));
  245. ASSERT_FALSE(data.prop('c'));
  246. auto prop = data.prop(static_cast<entt::id_type>(property_type::value));
  247. ASSERT_TRUE(prop);
  248. ASSERT_EQ(prop.value(), 3);
  249. }
  250. TEST_F(MetaData, GetMetaAnyArg) {
  251. using namespace entt::literals;
  252. entt::meta_any any{clazz{}};
  253. any.cast<clazz &>().i = 3;
  254. const auto value = entt::resolve<clazz>().data("i"_hs).get(any);
  255. ASSERT_TRUE(value);
  256. ASSERT_TRUE(static_cast<bool>(value.cast<int>()));
  257. ASSERT_EQ(value.cast<int>(), 3);
  258. }
  259. TEST_F(MetaData, GetInvalidArg) {
  260. using namespace entt::literals;
  261. auto instance = 0;
  262. ASSERT_FALSE(entt::resolve<clazz>().data("i"_hs).get(instance));
  263. }
  264. TEST_F(MetaData, SetMetaAnyArg) {
  265. using namespace entt::literals;
  266. entt::meta_any any{clazz{}};
  267. const entt::meta_any value{1};
  268. ASSERT_EQ(any.cast<clazz>().i, 0);
  269. ASSERT_TRUE(entt::resolve<clazz>().data("i"_hs).set(any, value));
  270. ASSERT_EQ(any.cast<clazz>().i, 1);
  271. }
  272. TEST_F(MetaData, SetInvalidArg) {
  273. using namespace entt::literals;
  274. ASSERT_FALSE(entt::resolve<clazz>().data("i"_hs).set({}, 'c'));
  275. }
  276. TEST_F(MetaData, SetCast) {
  277. using namespace entt::literals;
  278. clazz instance{};
  279. ASSERT_EQ(base::counter, 0);
  280. ASSERT_TRUE(entt::resolve<clazz>().data("base"_hs).set(instance, derived{}));
  281. ASSERT_EQ(base::counter, 1);
  282. }
  283. TEST_F(MetaData, SetConvert) {
  284. using namespace entt::literals;
  285. clazz instance{};
  286. clazz::h = 1;
  287. ASSERT_EQ(instance.i, 0);
  288. ASSERT_TRUE(entt::resolve<clazz>().data("i"_hs).set(instance, instance));
  289. ASSERT_EQ(instance.i, 1);
  290. }
  291. TEST_F(MetaData, SetByRef) {
  292. using namespace entt::literals;
  293. entt::meta_any any{clazz{}};
  294. int value{1};
  295. ASSERT_EQ(any.cast<clazz>().i, 0);
  296. ASSERT_TRUE(entt::resolve<clazz>().data("i"_hs).set(any, entt::forward_as_meta(value)));
  297. ASSERT_EQ(any.cast<clazz>().i, 1);
  298. value = 3;
  299. auto wrapper = entt::forward_as_meta(value);
  300. ASSERT_TRUE(entt::resolve<clazz>().data("i"_hs).set(any, wrapper.as_ref()));
  301. ASSERT_EQ(any.cast<clazz>().i, 3);
  302. }
  303. TEST_F(MetaData, SetByConstRef) {
  304. using namespace entt::literals;
  305. entt::meta_any any{clazz{}};
  306. int value{1};
  307. ASSERT_EQ(any.cast<clazz>().i, 0);
  308. ASSERT_TRUE(entt::resolve<clazz>().data("i"_hs).set(any, entt::forward_as_meta(std::as_const(value))));
  309. ASSERT_EQ(any.cast<clazz>().i, 1);
  310. value = 3;
  311. auto wrapper = entt::forward_as_meta(std::as_const(value));
  312. ASSERT_TRUE(entt::resolve<clazz>().data("i"_hs).set(any, wrapper.as_ref()));
  313. ASSERT_EQ(any.cast<clazz>().i, 3);
  314. }
  315. TEST_F(MetaData, SetterGetterAsFreeFunctions) {
  316. using namespace entt::literals;
  317. auto data = entt::resolve<setter_getter>().data("x"_hs);
  318. setter_getter instance{};
  319. ASSERT_TRUE(data);
  320. ASSERT_EQ(data.arity(), 1u);
  321. ASSERT_EQ(data.type(), entt::resolve<int>());
  322. ASSERT_EQ(data.arg(0u), entt::resolve<int>());
  323. ASSERT_FALSE(data.is_const());
  324. ASSERT_FALSE(data.is_static());
  325. ASSERT_EQ(data.get(instance).cast<int>(), 0);
  326. ASSERT_TRUE(data.set(instance, 1));
  327. ASSERT_EQ(data.get(instance).cast<int>(), 1);
  328. }
  329. TEST_F(MetaData, SetterGetterAsMemberFunctions) {
  330. using namespace entt::literals;
  331. auto data = entt::resolve<setter_getter>().data("y"_hs);
  332. setter_getter instance{};
  333. ASSERT_TRUE(data);
  334. ASSERT_EQ(data.arity(), 1u);
  335. ASSERT_EQ(data.type(), entt::resolve<int>());
  336. ASSERT_EQ(data.arg(0u), entt::resolve<double>());
  337. ASSERT_FALSE(data.is_const());
  338. ASSERT_FALSE(data.is_static());
  339. ASSERT_EQ(data.get(instance).cast<int>(), 0);
  340. ASSERT_TRUE(data.set(instance, 1.));
  341. ASSERT_EQ(data.get(instance).cast<int>(), 1);
  342. ASSERT_TRUE(data.set(instance, 3));
  343. ASSERT_EQ(data.get(instance).cast<int>(), 3);
  344. }
  345. TEST_F(MetaData, SetterGetterWithRefAsMemberFunctions) {
  346. using namespace entt::literals;
  347. auto data = entt::resolve<setter_getter>().data("w"_hs);
  348. setter_getter instance{};
  349. ASSERT_TRUE(data);
  350. ASSERT_EQ(data.arity(), 1u);
  351. ASSERT_EQ(data.type(), entt::resolve<int>());
  352. ASSERT_EQ(data.arg(0u), entt::resolve<int>());
  353. ASSERT_FALSE(data.is_const());
  354. ASSERT_FALSE(data.is_static());
  355. ASSERT_EQ(data.get(instance).cast<int>(), 0);
  356. ASSERT_TRUE(data.set(instance, 1));
  357. ASSERT_EQ(data.get(instance).cast<int>(), 1);
  358. }
  359. TEST_F(MetaData, SetterGetterMixed) {
  360. using namespace entt::literals;
  361. auto data = entt::resolve<setter_getter>().data("z"_hs);
  362. setter_getter instance{};
  363. ASSERT_TRUE(data);
  364. ASSERT_EQ(data.arity(), 1u);
  365. ASSERT_EQ(data.type(), entt::resolve<int>());
  366. ASSERT_EQ(data.arg(0u), entt::resolve<int>());
  367. ASSERT_FALSE(data.is_const());
  368. ASSERT_FALSE(data.is_static());
  369. ASSERT_EQ(data.get(instance).cast<int>(), 0);
  370. ASSERT_TRUE(data.set(instance, 1));
  371. ASSERT_EQ(data.get(instance).cast<int>(), 1);
  372. }
  373. TEST_F(MetaData, SetterGetterReadOnly) {
  374. using namespace entt::literals;
  375. auto data = entt::resolve<setter_getter>().data("z_ro"_hs);
  376. setter_getter instance{};
  377. ASSERT_TRUE(data);
  378. ASSERT_EQ(data.arity(), 0u);
  379. ASSERT_EQ(data.type(), entt::resolve<int>());
  380. ASSERT_EQ(data.arg(0u), entt::meta_type{});
  381. ASSERT_TRUE(data.is_const());
  382. ASSERT_FALSE(data.is_static());
  383. ASSERT_EQ(data.get(instance).cast<int>(), 0);
  384. ASSERT_FALSE(data.set(instance, 1));
  385. ASSERT_EQ(data.get(instance).cast<int>(), 0);
  386. }
  387. TEST_F(MetaData, SetterGetterReadOnlyDataMember) {
  388. using namespace entt::literals;
  389. auto data = entt::resolve<setter_getter>().data("value"_hs);
  390. setter_getter instance{};
  391. ASSERT_TRUE(data);
  392. ASSERT_EQ(data.arity(), 0u);
  393. ASSERT_EQ(data.type(), entt::resolve<int>());
  394. ASSERT_EQ(data.arg(0u), entt::meta_type{});
  395. ASSERT_TRUE(data.is_const());
  396. ASSERT_FALSE(data.is_static());
  397. ASSERT_EQ(data.get(instance).cast<int>(), 0);
  398. ASSERT_FALSE(data.set(instance, 1));
  399. ASSERT_EQ(data.get(instance).cast<int>(), 0);
  400. }
  401. TEST_F(MetaData, MultiSetter) {
  402. using namespace entt::literals;
  403. auto data = entt::resolve<multi_setter>().data("value"_hs);
  404. multi_setter instance{};
  405. ASSERT_TRUE(data);
  406. ASSERT_EQ(data.arity(), 2u);
  407. ASSERT_EQ(data.type(), entt::resolve<int>());
  408. ASSERT_EQ(data.arg(0u), entt::resolve<double>());
  409. ASSERT_EQ(data.arg(1u), entt::resolve<const char *>());
  410. ASSERT_EQ(data.arg(2u), entt::meta_type{});
  411. ASSERT_FALSE(data.is_const());
  412. ASSERT_FALSE(data.is_static());
  413. ASSERT_EQ(data.get(instance).cast<int>(), 0);
  414. ASSERT_TRUE(data.set(instance, 1));
  415. ASSERT_EQ(data.get(instance).cast<int>(), 1);
  416. ASSERT_TRUE(data.set(instance, 2.));
  417. ASSERT_EQ(data.get(instance).cast<int>(), 2);
  418. ASSERT_FALSE(data.set(instance, std::string{"3"}));
  419. ASSERT_TRUE(data.set(instance, std::string{"3"}.c_str()));
  420. ASSERT_EQ(data.get(instance).cast<int>(), 3);
  421. }
  422. TEST_F(MetaData, ConstInstance) {
  423. using namespace entt::literals;
  424. clazz instance{};
  425. ASSERT_NE(entt::resolve<clazz>().data("i"_hs).get(instance).try_cast<int>(), nullptr);
  426. ASSERT_NE(entt::resolve<clazz>().data("i"_hs).get(instance).try_cast<const int>(), nullptr);
  427. ASSERT_EQ(entt::resolve<clazz>().data("i"_hs).get(std::as_const(instance)).try_cast<int>(), nullptr);
  428. // as_ref_t adapts to the constness of the passed object and returns const references in case
  429. ASSERT_NE(entt::resolve<clazz>().data("i"_hs).get(std::as_const(instance)).try_cast<const int>(), nullptr);
  430. ASSERT_TRUE(entt::resolve<clazz>().data("i"_hs).get(instance));
  431. ASSERT_TRUE(entt::resolve<clazz>().data("i"_hs).set(instance, 3));
  432. ASSERT_TRUE(entt::resolve<clazz>().data("i"_hs).get(std::as_const(instance)));
  433. ASSERT_FALSE(entt::resolve<clazz>().data("i"_hs).set(std::as_const(instance), 3));
  434. ASSERT_TRUE(entt::resolve<clazz>().data("ci"_hs).get(instance));
  435. ASSERT_TRUE(entt::resolve<clazz>().data("ci"_hs).set(instance, 3));
  436. ASSERT_TRUE(entt::resolve<clazz>().data("ci"_hs).get(std::as_const(instance)));
  437. ASSERT_FALSE(entt::resolve<clazz>().data("ci"_hs).set(std::as_const(instance), 3));
  438. ASSERT_TRUE(entt::resolve<clazz>().data("j"_hs).get(instance));
  439. ASSERT_FALSE(entt::resolve<clazz>().data("j"_hs).set(instance, 3));
  440. ASSERT_TRUE(entt::resolve<clazz>().data("j"_hs).get(std::as_const(instance)));
  441. ASSERT_FALSE(entt::resolve<clazz>().data("j"_hs).set(std::as_const(instance), 3));
  442. }
  443. TEST_F(MetaData, ArrayStatic) {
  444. using namespace entt::literals;
  445. auto data = entt::resolve<array>().data("global"_hs);
  446. ASSERT_TRUE(data);
  447. ASSERT_EQ(data.arity(), 1u);
  448. // NOLINTBEGIN(*-avoid-c-arrays)
  449. ASSERT_EQ(data.type(), entt::resolve<int[2]>());
  450. ASSERT_EQ(data.arg(0u), entt::resolve<int[2]>());
  451. // NOLINTEND(*-avoid-c-arrays)
  452. ASSERT_FALSE(data.is_const());
  453. ASSERT_TRUE(data.is_static());
  454. ASSERT_TRUE(data.type().is_array());
  455. ASSERT_FALSE(data.get({}));
  456. }
  457. TEST_F(MetaData, Array) {
  458. using namespace entt::literals;
  459. auto data = entt::resolve<array>().data("local"_hs);
  460. array instance{};
  461. ASSERT_TRUE(data);
  462. ASSERT_EQ(data.arity(), 1u);
  463. // NOLINTBEGIN(*-avoid-c-arrays)
  464. ASSERT_EQ(data.type(), entt::resolve<int[4]>());
  465. ASSERT_EQ(data.arg(0u), entt::resolve<int[4]>());
  466. // NOLINTEND(*-avoid-c-arrays)
  467. ASSERT_FALSE(data.is_const());
  468. ASSERT_FALSE(data.is_static());
  469. ASSERT_TRUE(data.type().is_array());
  470. ASSERT_FALSE(data.get(instance));
  471. }
  472. TEST_F(MetaData, AsVoid) {
  473. using namespace entt::literals;
  474. auto data = entt::resolve<clazz>().data("void"_hs);
  475. clazz instance{};
  476. ASSERT_TRUE(data);
  477. ASSERT_EQ(data.arity(), 1u);
  478. ASSERT_EQ(data.type(), entt::resolve<int>());
  479. ASSERT_EQ(data.arg(0u), entt::resolve<int>());
  480. ASSERT_TRUE(data.set(instance, 1));
  481. ASSERT_EQ(instance.i, 1);
  482. ASSERT_EQ(data.get(instance), entt::meta_any{std::in_place_type<void>});
  483. }
  484. TEST_F(MetaData, AsRef) {
  485. using namespace entt::literals;
  486. clazz instance{};
  487. auto data = entt::resolve<clazz>().data("i"_hs);
  488. ASSERT_TRUE(data);
  489. ASSERT_EQ(data.arity(), 1u);
  490. ASSERT_EQ(data.type(), entt::resolve<int>());
  491. ASSERT_EQ(data.arg(0u), entt::resolve<int>());
  492. ASSERT_NE(data.prop().cbegin(), data.prop().cend());
  493. ASSERT_EQ(instance.i, 0);
  494. data.get(instance).cast<int &>() = 3;
  495. ASSERT_EQ(instance.i, 3);
  496. }
  497. TEST_F(MetaData, AsConstRef) {
  498. using namespace entt::literals;
  499. clazz instance{};
  500. auto data = entt::resolve<clazz>().data("ci"_hs);
  501. ASSERT_EQ(instance.i, 0);
  502. ASSERT_EQ(data.arity(), 1u);
  503. ASSERT_EQ(data.type(), entt::resolve<int>());
  504. ASSERT_EQ(data.arg(0u), entt::resolve<int>());
  505. ASSERT_EQ(data.get(instance).cast<const int &>(), 0);
  506. ASSERT_EQ(data.get(instance).cast<int>(), 0);
  507. ASSERT_EQ(data.prop().cbegin(), data.prop().cend());
  508. ASSERT_EQ(instance.i, 0);
  509. }
  510. ENTT_DEBUG_TEST_F(MetaDataDeathTest, AsConstRef) {
  511. using namespace entt::literals;
  512. clazz instance{};
  513. auto data = entt::resolve<clazz>().data("ci"_hs);
  514. ASSERT_DEATH(data.get(instance).cast<int &>() = 3, "");
  515. }
  516. TEST_F(MetaData, SetGetBaseData) {
  517. using namespace entt::literals;
  518. auto type = entt::resolve<derived>();
  519. derived instance{};
  520. ASSERT_TRUE(type.data("value"_hs));
  521. ASSERT_EQ(instance.value, 3);
  522. ASSERT_TRUE(type.data("value"_hs).set(instance, 1));
  523. ASSERT_EQ(type.data("value"_hs).get(instance).cast<int>(), 1);
  524. ASSERT_EQ(instance.value, 1);
  525. }
  526. TEST_F(MetaData, SetGetFromBase) {
  527. using namespace entt::literals;
  528. auto type = entt::resolve<derived>();
  529. derived instance{};
  530. ASSERT_TRUE(type.data("value_from_base"_hs));
  531. ASSERT_EQ(instance.value, 3);
  532. ASSERT_TRUE(type.data("value_from_base"_hs).set(instance, 1));
  533. ASSERT_EQ(type.data("value_from_base"_hs).get(instance).cast<int>(), 1);
  534. ASSERT_EQ(instance.value, 1);
  535. }
  536. TEST_F(MetaData, ReRegistration) {
  537. using namespace entt::literals;
  538. SetUp();
  539. auto &&node = entt::internal::resolve<base>(entt::internal::meta_context::from(entt::locator<entt::meta_ctx>::value_or()));
  540. auto type = entt::resolve<base>();
  541. ASSERT_TRUE(node.details);
  542. ASSERT_FALSE(node.details->data.empty());
  543. ASSERT_EQ(node.details->data.size(), 1u);
  544. ASSERT_TRUE(type.data("value"_hs));
  545. entt::meta<base>().data<&base::value>("field"_hs);
  546. ASSERT_TRUE(node.details);
  547. ASSERT_EQ(node.details->data.size(), 2u);
  548. ASSERT_TRUE(type.data("value"_hs));
  549. ASSERT_TRUE(type.data("field"_hs));
  550. entt::meta<base>()
  551. .data<&base::value>("field"_hs)
  552. .traits(test::meta_traits::one)
  553. .custom<int>(3)
  554. // this should not overwrite traits and custom data
  555. .data<&base::value>("field"_hs);
  556. ASSERT_EQ(type.data("field"_hs).traits<test::meta_traits>(), test::meta_traits::one);
  557. ASSERT_NE(static_cast<const int *>(type.data("field"_hs).custom()), nullptr);
  558. }
  559. TEST_F(MetaData, CollisionAndReuse) {
  560. using namespace entt::literals;
  561. ASSERT_TRUE(entt::resolve<clazz>().data("j"_hs));
  562. ASSERT_FALSE(entt::resolve<clazz>().data("cj"_hs));
  563. ASSERT_TRUE(entt::resolve<clazz>().data("j"_hs).is_const());
  564. ASSERT_NO_THROW(entt::meta<clazz>().data<&clazz::i>("j"_hs));
  565. ASSERT_NO_THROW(entt::meta<clazz>().data<&clazz::j>("cj"_hs));
  566. ASSERT_TRUE(entt::resolve<clazz>().data("j"_hs));
  567. ASSERT_TRUE(entt::resolve<clazz>().data("cj"_hs));
  568. ASSERT_FALSE(entt::resolve<clazz>().data("j"_hs).is_const());
  569. }