1 #include <gtest/gtest.h>
2 #include <entt/core/hashed_string.hpp>
3 #include <entt/meta/container.hpp>
4 #include <entt/meta/factory.hpp>
5 #include <entt/meta/meta.hpp>
6 #include <entt/meta/resolve.hpp>
7
8 struct MetaContainer: ::testing::Test {
SetUpMetaContainer9 void SetUp() override {
10 using namespace entt::literals;
11
12 entt::meta<double>()
13 .type("double"_hs)
14 .conv<int>();
15
16 entt::meta<int>()
17 .type("int"_hs)
18 .conv<char>();
19 }
20
TearDownMetaContainer21 void TearDown() override {
22 for(auto type: entt::resolve()) {
23 type.reset();
24 }
25 }
26 };
27
TEST_F(MetaContainer,InvalidContainer)28 TEST_F(MetaContainer, InvalidContainer) {
29 ASSERT_FALSE(entt::meta_any{42}.as_sequence_container());
30 ASSERT_FALSE(entt::meta_any{42}.as_associative_container());
31
32 ASSERT_FALSE((entt::meta_any{std::map<int, char>{}}.as_sequence_container()));
33 ASSERT_FALSE(entt::meta_any{std::vector<int>{}}.as_associative_container());
34 }
35
TEST_F(MetaContainer,EmptySequenceContainer)36 TEST_F(MetaContainer, EmptySequenceContainer) {
37 entt::meta_sequence_container container{};
38
39 ASSERT_FALSE(container);
40
41 entt::meta_any any{std::vector<int>{}};
42 container = any.as_sequence_container();
43
44 ASSERT_TRUE(container);
45 }
46
TEST_F(MetaContainer,EmptyAssociativeContainer)47 TEST_F(MetaContainer, EmptyAssociativeContainer) {
48 entt::meta_associative_container container{};
49
50 ASSERT_FALSE(container);
51
52 entt::meta_any any{std::map<int, char>{}};
53 container = any.as_associative_container();
54
55 ASSERT_TRUE(container);
56 }
57
TEST_F(MetaContainer,SequenceContainerIterator)58 TEST_F(MetaContainer, SequenceContainerIterator) {
59 std::vector<int> vec{2, 3, 4};
60 auto any = entt::forward_as_meta(vec);
61 entt::meta_sequence_container::iterator first{};
62 auto view = any.as_sequence_container();
63
64 ASSERT_FALSE(first);
65
66 first = view.begin();
67 const auto last = view.end();
68
69 ASSERT_TRUE(first);
70 ASSERT_TRUE(last);
71
72 ASSERT_FALSE(first == last);
73 ASSERT_TRUE(first != last);
74
75 ASSERT_NE(first, last);
76 ASSERT_EQ((*(first++)).cast<int>(), 2);
77 ASSERT_EQ((*(++first)).cast<int>(), 4);
78 ASSERT_NE(first++, last);
79 ASSERT_EQ(first, last);
80
81 ASSERT_TRUE(first == last);
82 ASSERT_FALSE(first != last);
83 }
84
TEST_F(MetaContainer,AssociativeContainerIterator)85 TEST_F(MetaContainer, AssociativeContainerIterator) {
86 std::map<int, char> map{{2, 'c'}, {3, 'd'}, {4, 'e'}};
87 auto any = entt::forward_as_meta(map);
88 entt::meta_associative_container::iterator first{};
89 auto view = any.as_associative_container();
90
91 ASSERT_FALSE(first);
92
93 first = view.begin();
94 const auto last = view.end();
95
96 ASSERT_TRUE(first);
97 ASSERT_TRUE(last);
98
99 ASSERT_FALSE(first == last);
100 ASSERT_TRUE(first != last);
101
102 ASSERT_NE(first, last);
103 ASSERT_EQ((*(first++)).first.cast<int>(), 2);
104 ASSERT_EQ((*(++first)).second.cast<char>(), 'e');
105 ASSERT_NE(first++, last);
106 ASSERT_EQ(first, last);
107
108 ASSERT_TRUE(first == last);
109 ASSERT_FALSE(first != last);
110 }
111
TEST_F(MetaContainer,StdVector)112 TEST_F(MetaContainer, StdVector) {
113 std::vector<int> vec{};
114 auto any = entt::forward_as_meta(vec);
115
116 auto view = any.as_sequence_container();
117
118 ASSERT_TRUE(view);
119 ASSERT_EQ(view.value_type(), entt::resolve<int>());
120
121 ASSERT_EQ(view.size(), 0u);
122 ASSERT_EQ(view.begin(), view.end());
123 ASSERT_TRUE(view.resize(3u));
124 ASSERT_EQ(view.size(), 3u);
125 ASSERT_NE(view.begin(), view.end());
126
127 view[0].cast<int &>() = 2;
128 view[1].cast<int &>() = 3;
129 view[2].cast<int &>() = 4;
130
131 ASSERT_EQ(view[1u].cast<int>(), 3);
132
133 auto it = view.begin();
134 auto ret = view.insert(it, 0);
135
136 ASSERT_TRUE(ret.second);
137 ASSERT_FALSE(view.insert(ret.first, 'c').second);
138 ASSERT_TRUE(view.insert(++ret.first, 1.).second);
139
140 ASSERT_EQ(view.size(), 5u);
141 ASSERT_EQ((*view.begin()).cast<int>(), 0);
142 ASSERT_EQ((*++view.begin()).cast<int>(), 1);
143
144 it = view.begin();
145 ret = view.erase(it);
146
147 ASSERT_TRUE(ret.second);
148 ASSERT_EQ(view.size(), 4u);
149 ASSERT_EQ((*ret.first).cast<int>(), 1);
150
151 ASSERT_TRUE(view.clear());
152 ASSERT_EQ(view.size(), 0u);
153 }
154
TEST_F(MetaContainer,StdArray)155 TEST_F(MetaContainer, StdArray) {
156 std::array<int, 3> arr{};
157 auto any = entt::forward_as_meta(arr);
158
159 auto view = any.as_sequence_container();
160
161 ASSERT_TRUE(view);
162 ASSERT_EQ(view.value_type(), entt::resolve<int>());
163
164 ASSERT_EQ(view.size(), 3u);
165 ASSERT_NE(view.begin(), view.end());
166 ASSERT_FALSE(view.resize(5u));
167 ASSERT_EQ(view.size(), 3u);
168
169 view[0].cast<int &>() = 2;
170 view[1].cast<int &>() = 3;
171 view[2].cast<int &>() = 4;
172
173 ASSERT_EQ(view[1u].cast<int>(), 3);
174
175 auto it = view.begin();
176 auto ret = view.insert(it, 0);
177
178 ASSERT_FALSE(ret.second);
179 ASSERT_FALSE(view.insert(it, 'c').second);
180 ASSERT_FALSE(view.insert(++it, 1).second);
181
182 ASSERT_EQ(view.size(), 3u);
183 ASSERT_EQ((*view.begin()).cast<int>(), 2);
184 ASSERT_EQ((*++view.begin()).cast<int>(), 3);
185
186 it = view.begin();
187 ret = view.erase(it);
188
189 ASSERT_FALSE(ret.second);
190 ASSERT_EQ(view.size(), 3u);
191 ASSERT_EQ((*it).cast<int>(), 2);
192
193 ASSERT_FALSE(view.clear());
194 ASSERT_EQ(view.size(), 3u);
195 }
196
TEST_F(MetaContainer,StdMap)197 TEST_F(MetaContainer, StdMap) {
198 std::map<int, char> map{{2, 'c'}, {3, 'd'}, {4, 'e'}};
199 auto any = entt::forward_as_meta(map);
200
201 auto view = any.as_associative_container();
202
203 ASSERT_TRUE(view);
204 ASSERT_FALSE(view.key_only());
205 ASSERT_EQ(view.key_type(), entt::resolve<int>());
206 ASSERT_EQ(view.mapped_type(), entt::resolve<char>());
207 ASSERT_EQ(view.value_type(), (entt::resolve<std::pair<const int, char>>()));
208
209 ASSERT_EQ(view.size(), 3u);
210 ASSERT_NE(view.begin(), view.end());
211
212 ASSERT_EQ((*view.find(3)).second.cast<char>(), 'd');
213
214 ASSERT_FALSE(view.insert('a', 'a'));
215 ASSERT_FALSE(view.insert(1, 1.));
216
217 ASSERT_TRUE(view.insert(0, 'a'));
218 ASSERT_TRUE(view.insert(1., static_cast<int>('b')));
219
220 ASSERT_EQ(view.size(), 5u);
221 ASSERT_EQ((*view.find(0)).second.cast<char>(), 'a');
222 ASSERT_EQ((*view.find(1.)).second.cast<char>(), 'b');
223
224 ASSERT_FALSE(view.erase('c'));
225 ASSERT_EQ(view.size(), 5u);
226 ASSERT_FALSE(view.find('c'));
227
228 ASSERT_TRUE(view.erase(0));
229 ASSERT_EQ(view.size(), 4u);
230 ASSERT_EQ(view.find(0), view.end());
231
232 (*view.find(1)).second.cast<char &>() = 'f';
233
234 ASSERT_EQ((*view.find(1)).second.cast<char>(), 'f');
235
236 ASSERT_TRUE(view.erase(1.));
237 ASSERT_TRUE(view.clear());
238 ASSERT_EQ(view.size(), 0u);
239 }
240
TEST_F(MetaContainer,StdSet)241 TEST_F(MetaContainer, StdSet) {
242 std::set<int> set{2, 3, 4};
243 auto any = entt::forward_as_meta(set);
244
245 auto view = any.as_associative_container();
246
247 ASSERT_TRUE(view);
248 ASSERT_TRUE(view.key_only());
249 ASSERT_EQ(view.key_type(), entt::resolve<int>());
250 ASSERT_EQ(view.mapped_type(), entt::meta_type{});
251 ASSERT_EQ(view.value_type(), entt::resolve<int>());
252
253 ASSERT_EQ(view.size(), 3u);
254 ASSERT_NE(view.begin(), view.end());
255
256 ASSERT_EQ((*view.find(3)).first.cast<int>(), 3);
257
258 ASSERT_FALSE(view.insert('0'));
259
260 ASSERT_TRUE(view.insert(0));
261 ASSERT_TRUE(view.insert(1));
262
263 ASSERT_EQ(view.size(), 5u);
264 ASSERT_EQ((*view.find(0)).first.cast<int>(), 0);
265 ASSERT_EQ((*view.find(1.)).first.cast<int>(), 1);
266
267 ASSERT_FALSE(view.erase('c'));
268 ASSERT_EQ(view.size(), 5u);
269 ASSERT_FALSE(view.find('c'));
270
271 ASSERT_TRUE(view.erase(0));
272 ASSERT_EQ(view.size(), 4u);
273 ASSERT_EQ(view.find(0), view.end());
274
275 ASSERT_EQ((*view.find(1)).first.try_cast<int>(), nullptr);
276 ASSERT_NE((*view.find(1)).first.try_cast<const int>(), nullptr);
277 ASSERT_EQ((*view.find(1)).first.cast<const int &>(), 1);
278
279 ASSERT_TRUE(view.erase(1.));
280 ASSERT_TRUE(view.clear());
281 ASSERT_EQ(view.size(), 0u);
282 }
283
TEST_F(MetaContainer,ConstSequenceContainer)284 TEST_F(MetaContainer, ConstSequenceContainer) {
285 std::vector<int> vec{};
286 auto any = entt::forward_as_meta(std::as_const(vec));
287
288 auto view = any.as_sequence_container();
289
290 ASSERT_TRUE(view);
291 ASSERT_EQ(view.value_type(), entt::resolve<int>());
292
293 ASSERT_EQ(view.size(), 0u);
294 ASSERT_EQ(view.begin(), view.end());
295 ASSERT_FALSE(view.resize(3u));
296 ASSERT_EQ(view.size(), 0u);
297 ASSERT_EQ(view.begin(), view.end());
298
299 vec.push_back(42);
300
301 ASSERT_EQ(view.size(), 1u);
302 ASSERT_NE(view.begin(), view.end());
303
304 ASSERT_DEATH(view[0].cast<int &>() = 2, "");
305 ASSERT_EQ(view[0].cast<const int &>(), 42);
306
307 auto it = view.begin();
308 auto ret = view.insert(it, 0);
309
310 ASSERT_FALSE(ret.second);
311 ASSERT_EQ(view.size(), 1u);
312 ASSERT_EQ((*it).cast<int>(), 42);
313 ASSERT_EQ(++it, view.end());
314
315 it = view.begin();
316 ret = view.erase(it);
317
318 ASSERT_FALSE(ret.second);
319 ASSERT_EQ(view.size(), 1u);
320
321 ASSERT_FALSE(view.clear());
322 ASSERT_EQ(view.size(), 1u);
323 }
324
TEST_F(MetaContainer,ConstKeyValueAssociativeContainer)325 TEST_F(MetaContainer, ConstKeyValueAssociativeContainer) {
326 std::map<int, char> map{};
327 auto any = entt::forward_as_meta(std::as_const(map));
328
329 auto view = any.as_associative_container();
330
331 ASSERT_TRUE(view);
332 ASSERT_FALSE(view.key_only());
333 ASSERT_EQ(view.key_type(), entt::resolve<int>());
334 ASSERT_EQ(view.mapped_type(), entt::resolve<char>());
335 ASSERT_EQ(view.value_type(), (entt::resolve<std::pair<const int, char>>()));
336
337 ASSERT_EQ(view.size(), 0u);
338 ASSERT_EQ(view.begin(), view.end());
339
340 map[2] = 'c';
341
342 ASSERT_EQ(view.size(), 1u);
343 ASSERT_NE(view.begin(), view.end());
344
345 ASSERT_DEATH((*view.find(2)).second.cast<char &>() = 'a', "");
346 ASSERT_EQ((*view.find(2)).second.cast<const char &>(), 'c');
347
348 ASSERT_FALSE(view.insert(0, 'a'));
349 ASSERT_EQ(view.size(), 1u);
350 ASSERT_EQ(view.find(0), view.end());
351 ASSERT_EQ((*view.find(2)).second.cast<char>(), 'c');
352
353 ASSERT_FALSE(view.erase(2));
354 ASSERT_EQ(view.size(), 1u);
355 ASSERT_NE(view.find(2), view.end());
356
357 ASSERT_FALSE(view.clear());
358 ASSERT_EQ(view.size(), 1u);
359 }
360
TEST_F(MetaContainer,ConstKeyOnlyAssociativeContainer)361 TEST_F(MetaContainer, ConstKeyOnlyAssociativeContainer) {
362 std::set<int> set{};
363 auto any = entt::forward_as_meta(std::as_const(set));
364
365 auto view = any.as_associative_container();
366
367 ASSERT_TRUE(view);
368 ASSERT_TRUE(view.key_only());
369 ASSERT_EQ(view.key_type(), entt::resolve<int>());
370 ASSERT_EQ(view.mapped_type(), entt::meta_type{});
371 ASSERT_EQ(view.value_type(), (entt::resolve<int>()));
372
373 ASSERT_EQ(view.size(), 0u);
374 ASSERT_EQ(view.begin(), view.end());
375
376 set.insert(2);
377
378 ASSERT_EQ(view.size(), 1u);
379 ASSERT_NE(view.begin(), view.end());
380
381 ASSERT_EQ((*view.find(2)).first.try_cast<int>(), nullptr);
382 ASSERT_NE((*view.find(2)).first.try_cast<const int>(), nullptr);
383 ASSERT_EQ((*view.find(2)).first.cast<int>(), 2);
384 ASSERT_EQ((*view.find(2)).first.cast<const int &>(), 2);
385
386 ASSERT_FALSE(view.insert(0));
387 ASSERT_EQ(view.size(), 1u);
388 ASSERT_EQ(view.find(0), view.end());
389 ASSERT_EQ((*view.find(2)).first.cast<int>(), 2);
390
391 ASSERT_FALSE(view.erase(2));
392 ASSERT_EQ(view.size(), 1u);
393 ASSERT_NE(view.find(2), view.end());
394
395 ASSERT_FALSE(view.clear());
396 ASSERT_EQ(view.size(), 1u);
397 }
398
TEST_F(MetaContainer,SequenceContainerConstMetaAny)399 TEST_F(MetaContainer, SequenceContainerConstMetaAny) {
400 auto test = [](const entt::meta_any any) {
401 auto view = any.as_sequence_container();
402
403 ASSERT_TRUE(view);
404 ASSERT_EQ(view.value_type(), entt::resolve<int>());
405 ASSERT_DEATH(view[0].cast<int &>() = 2, "");
406 ASSERT_EQ(view[0].cast<const int &>(), 42);
407 };
408
409 std::vector<int> vec{42};
410
411 test(vec);
412 test(entt::forward_as_meta(vec));
413 test(entt::forward_as_meta(std::as_const(vec)));
414 }
415
TEST_F(MetaContainer,KeyValueAssociativeContainerConstMetaAny)416 TEST_F(MetaContainer, KeyValueAssociativeContainerConstMetaAny) {
417 auto test = [](const entt::meta_any any) {
418 auto view = any.as_associative_container();
419
420 ASSERT_TRUE(view);
421 ASSERT_EQ(view.value_type(), (entt::resolve<std::pair<const int, char>>()));
422 ASSERT_DEATH((*view.find(2)).second.cast<char &>() = 'a', "");
423 ASSERT_EQ((*view.find(2)).second.cast<const char &>(), 'c');
424 };
425
426 std::map<int, char> map{{2, 'c'}};
427
428 test(map);
429 test(entt::forward_as_meta(map));
430 test(entt::forward_as_meta(std::as_const(map)));
431 }
432
TEST_F(MetaContainer,KeyOnlyAssociativeContainerConstMetaAny)433 TEST_F(MetaContainer, KeyOnlyAssociativeContainerConstMetaAny) {
434 auto test = [](const entt::meta_any any) {
435 auto view = any.as_associative_container();
436
437 ASSERT_TRUE(view);
438 ASSERT_EQ(view.value_type(), (entt::resolve<int>()));
439
440 ASSERT_EQ((*view.find(2)).first.try_cast<int>(), nullptr);
441 ASSERT_NE((*view.find(2)).first.try_cast<const int>(), nullptr);
442 ASSERT_EQ((*view.find(2)).first.cast<int>(), 2);
443 ASSERT_EQ((*view.find(2)).first.cast<const int &>(), 2);
444 };
445
446 std::set<int> set{2};
447
448 test(set);
449 test(entt::forward_as_meta(set));
450 test(entt::forward_as_meta(std::as_const(set)));
451 }
452
TEST_F(MetaContainer,StdVectorBool)453 TEST_F(MetaContainer, StdVectorBool) {
454 using proxy_type = typename std::vector<bool>::reference;
455 using const_proxy_type = typename std::vector<bool>::const_reference;
456
457 std::vector<bool> vec{};
458 auto any = entt::forward_as_meta(vec);
459 auto cany = std::as_const(any).as_ref();
460
461 auto view = any.as_sequence_container();
462 auto cview = cany.as_sequence_container();
463
464 ASSERT_TRUE(view);
465 ASSERT_EQ(view.value_type(), entt::resolve<bool>());
466
467 ASSERT_EQ(view.size(), 0u);
468 ASSERT_EQ(view.begin(), view.end());
469 ASSERT_TRUE(view.resize(3u));
470 ASSERT_EQ(view.size(), 3u);
471 ASSERT_NE(view.begin(), view.end());
472
473 view[0].cast<proxy_type>() = true;
474 view[1].cast<proxy_type>() = true;
475 view[2].cast<proxy_type>() = false;
476
477 ASSERT_EQ(cview[1u].cast<const_proxy_type>(), true);
478
479 auto it = view.begin();
480 auto ret = view.insert(it, true);
481
482 ASSERT_TRUE(ret.second);
483 ASSERT_FALSE(view.insert(ret.first, 'c').second);
484 ASSERT_TRUE(view.insert(++ret.first, false).second);
485
486 ASSERT_EQ(view.size(), 5u);
487 ASSERT_EQ((*view.begin()).cast<proxy_type>(), true);
488 ASSERT_EQ((*++cview.begin()).cast<const_proxy_type>(), false);
489
490 it = view.begin();
491 ret = view.erase(it);
492
493 ASSERT_TRUE(ret.second);
494 ASSERT_EQ(view.size(), 4u);
495 ASSERT_EQ((*ret.first).cast<proxy_type>(), false);
496
497 ASSERT_TRUE(view.clear());
498 ASSERT_EQ(cview.size(), 0u);
499 }
500