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 &registry) {
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) { reg.clear<int>(); };
209     auto t2 = +[](const void *, entt::registry &reg) { reg.clear<char>(); };
210     auto t3 = +[](const void *, entt::registry &reg) { reg.clear<double>(); };
211     auto t4 = +[](const void *, entt::registry &reg) { 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