meta_data.cpp 20 KB

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