1 #include <gtest/gtest.h>
2 #include <entt/entity/organizer.hpp>
3 #include <entt/entity/registry.hpp>
4
ro_int_rw_char_double(entt::view<entt::exclude_t<>,const int,char>,double &)5 void ro_int_rw_char_double(entt::view<entt::exclude_t<>, const int, char>, double &) {}
ro_char_rw_int(entt::view<entt::exclude_t<>,int,const char>)6 void ro_char_rw_int(entt::view<entt::exclude_t<>, int, const char>) {}
ro_char_rw_double(entt::view<entt::exclude_t<>,const char>,double &)7 void ro_char_rw_double(entt::view<entt::exclude_t<>, const char>, double &) {}
ro_int_double(entt::view<entt::exclude_t<>,const int>,const double &)8 void ro_int_double(entt::view<entt::exclude_t<>, const int>, const double &) {}
sync_point(entt::registry &,entt::view<entt::exclude_t<>,const int>)9 void sync_point(entt::registry &, entt::view<entt::exclude_t<>, const int>) {}
10
11 struct clazz {
ro_int_char_doubleclazz12 void ro_int_char_double(entt::view<entt::exclude_t<>, const int, const char>, const double &) {}
rw_intclazz13 void rw_int(entt::view<entt::exclude_t<>, int>) {}
rw_int_charclazz14 void rw_int_char(entt::view<entt::exclude_t<>, int, char>) {}
rw_int_char_doubleclazz15 void rw_int_char_double(entt::view<entt::exclude_t<>, int, char>, double &) {}
16
ro_int_with_payloadclazz17 static void ro_int_with_payload(const clazz &, entt::view<entt::exclude_t<>, const int>) {}
ro_char_with_payloadclazz18 static void ro_char_with_payload(const clazz &, entt::view<entt::exclude_t<>, const char>) {}
ro_int_char_with_payloadclazz19 static void ro_int_char_with_payload(clazz &, entt::view<entt::exclude_t<>, const int, const char>) {}
20 };
21
to_args_integrity(entt::view<entt::exclude_t<>,int> view,std::size_t & value,entt::registry & registry)22 void to_args_integrity(entt::view<entt::exclude_t<>, int> view, std::size_t &value, entt::registry ®istry) {
23 value = view.size();
24 }
25
TEST(Organizer,EmplaceFreeFunction)26 TEST(Organizer, EmplaceFreeFunction) {
27 entt::organizer organizer;
28 entt::registry registry;
29
30 organizer.emplace<&ro_int_rw_char_double>("t1");
31 organizer.emplace<&ro_char_rw_int>("t2");
32 organizer.emplace<&ro_char_rw_double>("t3");
33 organizer.emplace<&ro_int_double>("t4");
34
35 const auto graph = organizer.graph();
36
37 ASSERT_EQ(graph.size(), 4u);
38
39 ASSERT_STREQ(graph[0u].name(), "t1");
40 ASSERT_STREQ(graph[1u].name(), "t2");
41 ASSERT_STREQ(graph[2u].name(), "t3");
42 ASSERT_STREQ(graph[3u].name(), "t4");
43
44 ASSERT_EQ(graph[0u].ro_count(), 1u);
45 ASSERT_EQ(graph[1u].ro_count(), 1u);
46 ASSERT_EQ(graph[2u].ro_count(), 1u);
47 ASSERT_EQ(graph[3u].ro_count(), 2u);
48
49 ASSERT_EQ(graph[0u].rw_count(), 2u);
50 ASSERT_EQ(graph[1u].rw_count(), 1u);
51 ASSERT_EQ(graph[2u].rw_count(), 1u);
52 ASSERT_EQ(graph[3u].rw_count(), 0u);
53
54 ASSERT_NE(graph[0u].info(), graph[1u].info());
55 ASSERT_NE(graph[1u].info(), graph[2u].info());
56 ASSERT_NE(graph[2u].info(), graph[3u].info());
57
58 ASSERT_TRUE(graph[0u].top_level());
59 ASSERT_FALSE(graph[1u].top_level());
60 ASSERT_FALSE(graph[2u].top_level());
61 ASSERT_FALSE(graph[3u].top_level());
62
63 ASSERT_EQ(graph[0u].children().size(), 2u);
64 ASSERT_EQ(graph[1u].children().size(), 1u);
65 ASSERT_EQ(graph[2u].children().size(), 1u);
66 ASSERT_EQ(graph[3u].children().size(), 0u);
67
68 ASSERT_EQ(graph[0u].children()[0u], 1u);
69 ASSERT_EQ(graph[0u].children()[1u], 2u);
70 ASSERT_EQ(graph[1u].children()[0u], 3u);
71 ASSERT_EQ(graph[2u].children()[0u], 3u);
72
73 for(auto &&vertex: graph) {
74 ASSERT_NO_FATAL_FAILURE(vertex.callback()(vertex.data(), registry));
75 }
76
77 organizer.clear();
78
79 ASSERT_EQ(organizer.graph().size(), 0u);
80 }
81
TEST(Organizer,EmplaceMemberFunction)82 TEST(Organizer, EmplaceMemberFunction) {
83 entt::organizer organizer;
84 entt::registry registry;
85 clazz instance;
86
87 organizer.emplace<&clazz::ro_int_char_double>(instance, "t1");
88 organizer.emplace<&clazz::rw_int>(instance, "t2");
89 organizer.emplace<&clazz::rw_int_char>(instance, "t3");
90 organizer.emplace<&clazz::rw_int_char_double>(instance, "t4");
91
92 const auto graph = organizer.graph();
93
94 ASSERT_EQ(graph.size(), 4u);
95
96 ASSERT_STREQ(graph[0u].name(), "t1");
97 ASSERT_STREQ(graph[1u].name(), "t2");
98 ASSERT_STREQ(graph[2u].name(), "t3");
99 ASSERT_STREQ(graph[3u].name(), "t4");
100
101 ASSERT_EQ(graph[0u].ro_count(), 3u);
102 ASSERT_EQ(graph[1u].ro_count(), 0u);
103 ASSERT_EQ(graph[2u].ro_count(), 0u);
104 ASSERT_EQ(graph[3u].ro_count(), 0u);
105
106 ASSERT_EQ(graph[0u].rw_count(), 0u);
107 ASSERT_EQ(graph[1u].rw_count(), 1u);
108 ASSERT_EQ(graph[2u].rw_count(), 2u);
109 ASSERT_EQ(graph[3u].rw_count(), 3u);
110
111 ASSERT_NE(graph[0u].info(), graph[1u].info());
112 ASSERT_NE(graph[1u].info(), graph[2u].info());
113 ASSERT_NE(graph[2u].info(), graph[3u].info());
114
115 ASSERT_TRUE(graph[0u].top_level());
116 ASSERT_FALSE(graph[1u].top_level());
117 ASSERT_FALSE(graph[2u].top_level());
118 ASSERT_FALSE(graph[3u].top_level());
119
120 ASSERT_EQ(graph[0u].children().size(), 1u);
121 ASSERT_EQ(graph[1u].children().size(), 1u);
122 ASSERT_EQ(graph[2u].children().size(), 1u);
123 ASSERT_EQ(graph[3u].children().size(), 0u);
124
125 ASSERT_EQ(graph[0u].children()[0u], 1u);
126 ASSERT_EQ(graph[1u].children()[0u], 2u);
127 ASSERT_EQ(graph[2u].children()[0u], 3u);
128
129 for(auto &&vertex: graph) {
130 ASSERT_NO_FATAL_FAILURE(vertex.callback()(vertex.data(), registry));
131 }
132
133 organizer.clear();
134
135 ASSERT_EQ(organizer.graph().size(), 0u);
136 }
137
TEST(Organizer,EmplaceFreeFunctionWithPayload)138 TEST(Organizer, EmplaceFreeFunctionWithPayload) {
139 entt::organizer organizer;
140 entt::registry registry;
141 clazz instance;
142
143 organizer.emplace<&clazz::ro_int_char_double>(instance, "t1");
144 organizer.emplace<&clazz::ro_int_with_payload>(instance, "t2");
145 organizer.emplace<&clazz::ro_char_with_payload, const clazz>(instance, "t3");
146 organizer.emplace<&clazz::ro_int_char_with_payload, clazz>(instance, "t4");
147 organizer.emplace<&clazz::rw_int_char>(instance, "t5");
148
149 const auto graph = organizer.graph();
150
151 ASSERT_EQ(graph.size(), 5u);
152
153 ASSERT_STREQ(graph[0u].name(), "t1");
154 ASSERT_STREQ(graph[1u].name(), "t2");
155 ASSERT_STREQ(graph[2u].name(), "t3");
156 ASSERT_STREQ(graph[3u].name(), "t4");
157 ASSERT_STREQ(graph[4u].name(), "t5");
158
159 ASSERT_EQ(graph[0u].ro_count(), 3u);
160 ASSERT_EQ(graph[1u].ro_count(), 1u);
161 ASSERT_EQ(graph[2u].ro_count(), 2u);
162 ASSERT_EQ(graph[3u].ro_count(), 2u);
163 ASSERT_EQ(graph[4u].ro_count(), 0u);
164
165 ASSERT_EQ(graph[0u].rw_count(), 0u);
166 ASSERT_EQ(graph[1u].rw_count(), 0u);
167 ASSERT_EQ(graph[2u].rw_count(), 0u);
168 ASSERT_EQ(graph[3u].rw_count(), 1u);
169 ASSERT_EQ(graph[4u].rw_count(), 2u);
170
171 ASSERT_NE(graph[0u].info(), graph[1u].info());
172 ASSERT_NE(graph[1u].info(), graph[2u].info());
173 ASSERT_NE(graph[2u].info(), graph[3u].info());
174 ASSERT_NE(graph[3u].info(), graph[4u].info());
175
176 ASSERT_TRUE(graph[0u].top_level());
177 ASSERT_TRUE(graph[1u].top_level());
178 ASSERT_TRUE(graph[2u].top_level());
179 ASSERT_FALSE(graph[3u].top_level());
180 ASSERT_FALSE(graph[4u].top_level());
181
182 ASSERT_EQ(graph[0u].children().size(), 1u);
183 ASSERT_EQ(graph[1u].children().size(), 1u);
184 ASSERT_EQ(graph[2u].children().size(), 1u);
185 ASSERT_EQ(graph[3u].children().size(), 1u);
186 ASSERT_EQ(graph[4u].children().size(), 0u);
187
188 ASSERT_EQ(graph[0u].children()[0u], 4u);
189 ASSERT_EQ(graph[1u].children()[0u], 4u);
190 ASSERT_EQ(graph[2u].children()[0u], 3u);
191 ASSERT_EQ(graph[3u].children()[0u], 4u);
192
193 for(auto &&vertex: graph) {
194 ASSERT_NO_FATAL_FAILURE(vertex.callback()(vertex.data(), registry));
195 }
196
197 organizer.clear();
198
199 ASSERT_EQ(organizer.graph().size(), 0u);
200 }
201
TEST(Organizer,EmplaceDirectFunction)202 TEST(Organizer, EmplaceDirectFunction) {
203 entt::organizer organizer;
204 entt::registry registry;
205 clazz instance;
206
207 // no aggressive comdat
208 auto t1 = +[](const void *, entt::registry ®) { reg.clear<int>(); };
209 auto t2 = +[](const void *, entt::registry ®) { reg.clear<char>(); };
210 auto t3 = +[](const void *, entt::registry ®) { reg.clear<double>(); };
211 auto t4 = +[](const void *, entt::registry ®) { reg.clear(); };
212
213 organizer.emplace<int>(t1, nullptr, "t1");
214 organizer.emplace<const int>(t2, &instance, "t2");
215 organizer.emplace<const int, char>(t3, nullptr, "t3");
216 organizer.emplace<int, char, double>(t4, &instance, "t4");
217
218 const auto graph = organizer.graph();
219
220 ASSERT_EQ(graph.size(), 4u);
221
222 ASSERT_STREQ(graph[0u].name(), "t1");
223 ASSERT_STREQ(graph[1u].name(), "t2");
224 ASSERT_STREQ(graph[2u].name(), "t3");
225 ASSERT_STREQ(graph[3u].name(), "t4");
226
227 ASSERT_EQ(graph[0u].ro_count(), 0u);
228 ASSERT_EQ(graph[1u].ro_count(), 1u);
229 ASSERT_EQ(graph[2u].ro_count(), 1u);
230 ASSERT_EQ(graph[3u].ro_count(), 0u);
231
232 ASSERT_EQ(graph[0u].rw_count(), 1u);
233 ASSERT_EQ(graph[1u].rw_count(), 0u);
234 ASSERT_EQ(graph[2u].rw_count(), 1u);
235 ASSERT_EQ(graph[3u].rw_count(), 3u);
236
237 ASSERT_TRUE(graph[0u].callback() == t1);
238 ASSERT_TRUE(graph[1u].callback() == t2);
239 ASSERT_TRUE(graph[2u].callback() == t3);
240 ASSERT_TRUE(graph[3u].callback() == t4);
241
242 ASSERT_EQ(graph[0u].data(), nullptr);
243 ASSERT_EQ(graph[1u].data(), &instance);
244 ASSERT_EQ(graph[2u].data(), nullptr);
245 ASSERT_EQ(graph[3u].data(), &instance);
246
247 ASSERT_EQ(graph[0u].info(), entt::type_info{});
248 ASSERT_EQ(graph[1u].info(), entt::type_info{});
249 ASSERT_EQ(graph[2u].info(), entt::type_info{});
250 ASSERT_EQ(graph[3u].info(), entt::type_info{});
251
252 ASSERT_TRUE(graph[0u].top_level());
253 ASSERT_FALSE(graph[1u].top_level());
254 ASSERT_FALSE(graph[2u].top_level());
255 ASSERT_FALSE(graph[3u].top_level());
256
257 ASSERT_EQ(graph[0u].children().size(), 1u);
258 ASSERT_EQ(graph[1u].children().size(), 1u);
259 ASSERT_EQ(graph[2u].children().size(), 1u);
260 ASSERT_EQ(graph[3u].children().size(), 0u);
261
262 ASSERT_EQ(graph[0u].children()[0u], 1u);
263 ASSERT_EQ(graph[1u].children()[0u], 2u);
264 ASSERT_EQ(graph[2u].children()[0u], 3u);
265
266 for(auto &&vertex: graph) {
267 ASSERT_NO_FATAL_FAILURE(vertex.callback()(vertex.data(), registry));
268 }
269
270 organizer.clear();
271
272 ASSERT_EQ(organizer.graph().size(), 0u);
273 }
274
TEST(Organizer,SyncPoint)275 TEST(Organizer, SyncPoint) {
276 entt::organizer organizer;
277 entt::registry registry;
278 clazz instance;
279
280 organizer.emplace<&ro_int_double>("before");
281 organizer.emplace<&sync_point>("sync_1");
282 organizer.emplace<&clazz::ro_int_char_double>(instance, "mid_1");
283 organizer.emplace<&ro_int_double>("mid_2");
284 organizer.emplace<&sync_point>("sync_2");
285 organizer.emplace<&ro_int_double>("after");
286
287 const auto graph = organizer.graph();
288
289 ASSERT_EQ(graph.size(), 6u);
290
291 ASSERT_STREQ(graph[0u].name(), "before");
292 ASSERT_STREQ(graph[1u].name(), "sync_1");
293 ASSERT_STREQ(graph[2u].name(), "mid_1");
294 ASSERT_STREQ(graph[3u].name(), "mid_2");
295 ASSERT_STREQ(graph[4u].name(), "sync_2");
296 ASSERT_STREQ(graph[5u].name(), "after");
297
298 ASSERT_TRUE(graph[0u].top_level());
299 ASSERT_FALSE(graph[1u].top_level());
300 ASSERT_FALSE(graph[2u].top_level());
301 ASSERT_FALSE(graph[3u].top_level());
302 ASSERT_FALSE(graph[4u].top_level());
303 ASSERT_FALSE(graph[5u].top_level());
304
305 ASSERT_EQ(graph[0u].children().size(), 1u);
306 ASSERT_EQ(graph[1u].children().size(), 2u);
307 ASSERT_EQ(graph[2u].children().size(), 1u);
308 ASSERT_EQ(graph[3u].children().size(), 1u);
309 ASSERT_EQ(graph[4u].children().size(), 1u);
310 ASSERT_EQ(graph[5u].children().size(), 0u);
311
312 ASSERT_EQ(graph[0u].children()[0u], 1u);
313 ASSERT_EQ(graph[1u].children()[0u], 2u);
314 ASSERT_EQ(graph[1u].children()[1u], 3u);
315 ASSERT_EQ(graph[2u].children()[0u], 4u);
316 ASSERT_EQ(graph[3u].children()[0u], 4u);
317 ASSERT_EQ(graph[4u].children()[0u], 5u);
318
319 for(auto &&vertex: graph) {
320 ASSERT_NO_FATAL_FAILURE(vertex.callback()(vertex.data(), registry));
321 }
322 }
323
TEST(Organizer,Override)324 TEST(Organizer, Override) {
325 entt::organizer organizer;
326
327 organizer.emplace<&ro_int_rw_char_double, const char, const double>("t1");
328 organizer.emplace<&ro_char_rw_double, const double>("t2");
329 organizer.emplace<&ro_int_double, double>("t3");
330
331 const auto graph = organizer.graph();
332
333 ASSERT_EQ(graph.size(), 3u);
334
335 ASSERT_STREQ(graph[0u].name(), "t1");
336 ASSERT_STREQ(graph[1u].name(), "t2");
337 ASSERT_STREQ(graph[2u].name(), "t3");
338
339 ASSERT_TRUE(graph[0u].top_level());
340 ASSERT_TRUE(graph[1u].top_level());
341 ASSERT_FALSE(graph[2u].top_level());
342
343 ASSERT_EQ(graph[0u].children().size(), 1u);
344 ASSERT_EQ(graph[1u].children().size(), 1u);
345 ASSERT_EQ(graph[2u].children().size(), 0u);
346
347 ASSERT_EQ(graph[0u].children()[0u], 2u);
348 ASSERT_EQ(graph[1u].children()[0u], 2u);
349 }
350
TEST(Organizer,Prepare)351 TEST(Organizer, Prepare) {
352 entt::organizer organizer;
353 entt::registry registry;
354 clazz instance;
355
356 organizer.emplace<&ro_int_double>();
357 organizer.emplace<&clazz::rw_int_char>(instance);
358
359 const auto graph = organizer.graph();
360
361 ASSERT_EQ(registry.try_ctx<int>(), nullptr);
362 ASSERT_EQ(registry.try_ctx<char>(), nullptr);
363 ASSERT_EQ(registry.try_ctx<double>(), nullptr);
364
365 for(auto &&vertex: graph) {
366 vertex.prepare(registry);
367 }
368
369 ASSERT_EQ(registry.try_ctx<int>(), nullptr);
370 ASSERT_EQ(registry.try_ctx<char>(), nullptr);
371 ASSERT_NE(registry.try_ctx<double>(), nullptr);
372 }
373
TEST(Organizer,Dependencies)374 TEST(Organizer, Dependencies) {
375 entt::organizer organizer;
376 clazz instance;
377
378 organizer.emplace<&ro_int_double>();
379 organizer.emplace<&clazz::rw_int_char>(instance);
380 organizer.emplace<char, const double>(+[](const void *, entt::registry &) {});
381
382 const auto graph = organizer.graph();
383 entt::type_info buffer[5u]{};
384
385 ASSERT_EQ(graph.size(), 3u);
386
387 ASSERT_EQ(graph[0u].ro_count(), 2u);
388 ASSERT_EQ(graph[0u].rw_count(), 0u);
389
390 ASSERT_EQ(graph[0u].ro_dependency(buffer, 0u), 0u);
391 ASSERT_EQ(graph[0u].rw_dependency(buffer, 2u), 0u);
392
393 ASSERT_EQ(graph[0u].ro_dependency(buffer, 5u), 2u);
394 ASSERT_EQ(buffer[0u], entt::type_id<int>());
395 ASSERT_EQ(buffer[1u], entt::type_id<double>());
396
397 ASSERT_EQ(graph[1u].ro_count(), 0u);
398 ASSERT_EQ(graph[1u].rw_count(), 2u);
399
400 ASSERT_EQ(graph[1u].ro_dependency(buffer, 2u), 0u);
401 ASSERT_EQ(graph[1u].rw_dependency(buffer, 0u), 0u);
402
403 ASSERT_EQ(graph[1u].rw_dependency(buffer, 5u), 2u);
404 ASSERT_EQ(buffer[0u], entt::type_id<int>());
405 ASSERT_EQ(buffer[1u], entt::type_id<char>());
406
407 ASSERT_EQ(graph[2u].ro_count(), 1u);
408 ASSERT_EQ(graph[2u].rw_count(), 1u);
409
410 ASSERT_EQ(graph[2u].ro_dependency(buffer, 2u), 1u);
411 ASSERT_EQ(graph[2u].rw_dependency(buffer, 0u), 0u);
412
413 ASSERT_EQ(graph[2u].ro_dependency(buffer, 5u), 1u);
414 ASSERT_EQ(buffer[0u], entt::type_id<double>());
415
416 ASSERT_EQ(graph[2u].rw_dependency(buffer, 5u), 1u);
417 ASSERT_EQ(buffer[0u], entt::type_id<char>());
418 }
419
TEST(Organizer,ToArgsIntegrity)420 TEST(Organizer, ToArgsIntegrity) {
421 entt::organizer organizer;
422 entt::registry registry;
423
424 organizer.emplace<&to_args_integrity>();
425 registry.set<std::size_t>(42u);
426
427 auto graph = organizer.graph();
428 graph[0u].callback()(graph[0u].data(), registry);
429
430 ASSERT_EQ(registry.ctx<std::size_t>(), 0u);
431 }
432