#include #include #include #include void ro_int_rw_char_double(entt::view>, double &) {} void ro_char_rw_int(entt::view>) {} void ro_char_rw_double(entt::view>, double &) {} void ro_int_double(entt::view>, const double &) {} void sync_point(entt::registry &, entt::view>) {} struct clazz { void ro_int_char_double(entt::view>, const double &) {} void rw_int(entt::view>) {} void rw_int_char(entt::view>) {} void rw_int_char_double(entt::view>, double &) {} static void ro_int_with_payload(const clazz &, entt::view>) {} static void ro_char_with_payload(const clazz &, entt::view>) {} static void ro_int_char_with_payload(clazz &, entt::view>) {} }; void to_args_integrity(entt::view> view, std::size_t &value, entt::registry ®istry) { value = view.size(); } TEST(Organizer, EmplaceFreeFunction) { entt::organizer organizer; entt::registry registry; organizer.emplace<&ro_int_rw_char_double>("t1"); organizer.emplace<&ro_char_rw_int>("t2"); organizer.emplace<&ro_char_rw_double>("t3"); organizer.emplace<&ro_int_double>("t4"); const auto graph = organizer.graph(); ASSERT_EQ(graph.size(), 4u); ASSERT_STREQ(graph[0u].name(), "t1"); ASSERT_STREQ(graph[1u].name(), "t2"); ASSERT_STREQ(graph[2u].name(), "t3"); ASSERT_STREQ(graph[3u].name(), "t4"); ASSERT_EQ(graph[0u].ro_count(), 1u); ASSERT_EQ(graph[1u].ro_count(), 1u); ASSERT_EQ(graph[2u].ro_count(), 1u); ASSERT_EQ(graph[3u].ro_count(), 2u); ASSERT_EQ(graph[0u].rw_count(), 2u); ASSERT_EQ(graph[1u].rw_count(), 1u); ASSERT_EQ(graph[2u].rw_count(), 1u); ASSERT_EQ(graph[3u].rw_count(), 0u); ASSERT_NE(graph[0u].info(), graph[1u].info()); ASSERT_NE(graph[1u].info(), graph[2u].info()); ASSERT_NE(graph[2u].info(), graph[3u].info()); ASSERT_TRUE(graph[0u].top_level()); ASSERT_FALSE(graph[1u].top_level()); ASSERT_FALSE(graph[2u].top_level()); ASSERT_FALSE(graph[3u].top_level()); ASSERT_EQ(graph[0u].children().size(), 2u); ASSERT_EQ(graph[1u].children().size(), 1u); ASSERT_EQ(graph[2u].children().size(), 1u); ASSERT_EQ(graph[3u].children().size(), 0u); ASSERT_EQ(graph[0u].children()[0u], 1u); ASSERT_EQ(graph[0u].children()[1u], 2u); ASSERT_EQ(graph[1u].children()[0u], 3u); ASSERT_EQ(graph[2u].children()[0u], 3u); for(auto &&vertex: graph) { ASSERT_NO_FATAL_FAILURE(vertex.callback()(vertex.data(), registry)); } organizer.clear(); ASSERT_EQ(organizer.graph().size(), 0u); } TEST(Organizer, EmplaceMemberFunction) { entt::organizer organizer; entt::registry registry; clazz instance; organizer.emplace<&clazz::ro_int_char_double>(instance, "t1"); organizer.emplace<&clazz::rw_int>(instance, "t2"); organizer.emplace<&clazz::rw_int_char>(instance, "t3"); organizer.emplace<&clazz::rw_int_char_double>(instance, "t4"); const auto graph = organizer.graph(); ASSERT_EQ(graph.size(), 4u); ASSERT_STREQ(graph[0u].name(), "t1"); ASSERT_STREQ(graph[1u].name(), "t2"); ASSERT_STREQ(graph[2u].name(), "t3"); ASSERT_STREQ(graph[3u].name(), "t4"); ASSERT_EQ(graph[0u].ro_count(), 3u); ASSERT_EQ(graph[1u].ro_count(), 0u); ASSERT_EQ(graph[2u].ro_count(), 0u); ASSERT_EQ(graph[3u].ro_count(), 0u); ASSERT_EQ(graph[0u].rw_count(), 0u); ASSERT_EQ(graph[1u].rw_count(), 1u); ASSERT_EQ(graph[2u].rw_count(), 2u); ASSERT_EQ(graph[3u].rw_count(), 3u); ASSERT_NE(graph[0u].info(), graph[1u].info()); ASSERT_NE(graph[1u].info(), graph[2u].info()); ASSERT_NE(graph[2u].info(), graph[3u].info()); ASSERT_TRUE(graph[0u].top_level()); ASSERT_FALSE(graph[1u].top_level()); ASSERT_FALSE(graph[2u].top_level()); ASSERT_FALSE(graph[3u].top_level()); ASSERT_EQ(graph[0u].children().size(), 1u); ASSERT_EQ(graph[1u].children().size(), 1u); ASSERT_EQ(graph[2u].children().size(), 1u); ASSERT_EQ(graph[3u].children().size(), 0u); ASSERT_EQ(graph[0u].children()[0u], 1u); ASSERT_EQ(graph[1u].children()[0u], 2u); ASSERT_EQ(graph[2u].children()[0u], 3u); for(auto &&vertex: graph) { ASSERT_NO_FATAL_FAILURE(vertex.callback()(vertex.data(), registry)); } organizer.clear(); ASSERT_EQ(organizer.graph().size(), 0u); } TEST(Organizer, EmplaceFreeFunctionWithPayload) { entt::organizer organizer; entt::registry registry; clazz instance; organizer.emplace<&clazz::ro_int_char_double>(instance, "t1"); organizer.emplace<&clazz::ro_int_with_payload>(instance, "t2"); organizer.emplace<&clazz::ro_char_with_payload, const clazz>(instance, "t3"); organizer.emplace<&clazz::ro_int_char_with_payload, clazz>(instance, "t4"); organizer.emplace<&clazz::rw_int_char>(instance, "t5"); const auto graph = organizer.graph(); ASSERT_EQ(graph.size(), 5u); ASSERT_STREQ(graph[0u].name(), "t1"); ASSERT_STREQ(graph[1u].name(), "t2"); ASSERT_STREQ(graph[2u].name(), "t3"); ASSERT_STREQ(graph[3u].name(), "t4"); ASSERT_STREQ(graph[4u].name(), "t5"); ASSERT_EQ(graph[0u].ro_count(), 3u); ASSERT_EQ(graph[1u].ro_count(), 1u); ASSERT_EQ(graph[2u].ro_count(), 2u); ASSERT_EQ(graph[3u].ro_count(), 2u); ASSERT_EQ(graph[4u].ro_count(), 0u); ASSERT_EQ(graph[0u].rw_count(), 0u); ASSERT_EQ(graph[1u].rw_count(), 0u); ASSERT_EQ(graph[2u].rw_count(), 0u); ASSERT_EQ(graph[3u].rw_count(), 1u); ASSERT_EQ(graph[4u].rw_count(), 2u); ASSERT_NE(graph[0u].info(), graph[1u].info()); ASSERT_NE(graph[1u].info(), graph[2u].info()); ASSERT_NE(graph[2u].info(), graph[3u].info()); ASSERT_NE(graph[3u].info(), graph[4u].info()); ASSERT_TRUE(graph[0u].top_level()); ASSERT_TRUE(graph[1u].top_level()); ASSERT_TRUE(graph[2u].top_level()); ASSERT_FALSE(graph[3u].top_level()); ASSERT_FALSE(graph[4u].top_level()); ASSERT_EQ(graph[0u].children().size(), 1u); ASSERT_EQ(graph[1u].children().size(), 1u); ASSERT_EQ(graph[2u].children().size(), 1u); ASSERT_EQ(graph[3u].children().size(), 1u); ASSERT_EQ(graph[4u].children().size(), 0u); ASSERT_EQ(graph[0u].children()[0u], 4u); ASSERT_EQ(graph[1u].children()[0u], 4u); ASSERT_EQ(graph[2u].children()[0u], 3u); ASSERT_EQ(graph[3u].children()[0u], 4u); for(auto &&vertex: graph) { ASSERT_NO_FATAL_FAILURE(vertex.callback()(vertex.data(), registry)); } organizer.clear(); ASSERT_EQ(organizer.graph().size(), 0u); } TEST(Organizer, EmplaceDirectFunction) { entt::organizer organizer; entt::registry registry; clazz instance; // no aggressive comdat auto t1 = +[](const void *, entt::registry ®) { reg.clear(); }; auto t2 = +[](const void *, entt::registry ®) { reg.clear(); }; auto t3 = +[](const void *, entt::registry ®) { reg.clear(); }; auto t4 = +[](const void *, entt::registry ®) { reg.clear(); }; organizer.emplace(t1, nullptr, "t1"); organizer.emplace(t2, &instance, "t2"); organizer.emplace(t3, nullptr, "t3"); organizer.emplace(t4, &instance, "t4"); const auto graph = organizer.graph(); ASSERT_EQ(graph.size(), 4u); ASSERT_STREQ(graph[0u].name(), "t1"); ASSERT_STREQ(graph[1u].name(), "t2"); ASSERT_STREQ(graph[2u].name(), "t3"); ASSERT_STREQ(graph[3u].name(), "t4"); ASSERT_EQ(graph[0u].ro_count(), 0u); ASSERT_EQ(graph[1u].ro_count(), 1u); ASSERT_EQ(graph[2u].ro_count(), 1u); ASSERT_EQ(graph[3u].ro_count(), 0u); ASSERT_EQ(graph[0u].rw_count(), 1u); ASSERT_EQ(graph[1u].rw_count(), 0u); ASSERT_EQ(graph[2u].rw_count(), 1u); ASSERT_EQ(graph[3u].rw_count(), 3u); ASSERT_TRUE(graph[0u].callback() == t1); ASSERT_TRUE(graph[1u].callback() == t2); ASSERT_TRUE(graph[2u].callback() == t3); ASSERT_TRUE(graph[3u].callback() == t4); ASSERT_EQ(graph[0u].data(), nullptr); ASSERT_EQ(graph[1u].data(), &instance); ASSERT_EQ(graph[2u].data(), nullptr); ASSERT_EQ(graph[3u].data(), &instance); ASSERT_EQ(graph[0u].info(), entt::type_id()); ASSERT_EQ(graph[1u].info(), entt::type_id()); ASSERT_EQ(graph[2u].info(), entt::type_id()); ASSERT_EQ(graph[3u].info(), entt::type_id()); ASSERT_TRUE(graph[0u].top_level()); ASSERT_FALSE(graph[1u].top_level()); ASSERT_FALSE(graph[2u].top_level()); ASSERT_FALSE(graph[3u].top_level()); ASSERT_EQ(graph[0u].children().size(), 1u); ASSERT_EQ(graph[1u].children().size(), 1u); ASSERT_EQ(graph[2u].children().size(), 1u); ASSERT_EQ(graph[3u].children().size(), 0u); ASSERT_EQ(graph[0u].children()[0u], 1u); ASSERT_EQ(graph[1u].children()[0u], 2u); ASSERT_EQ(graph[2u].children()[0u], 3u); for(auto &&vertex: graph) { ASSERT_NO_FATAL_FAILURE(vertex.callback()(vertex.data(), registry)); } organizer.clear(); ASSERT_EQ(organizer.graph().size(), 0u); } TEST(Organizer, SyncPoint) { entt::organizer organizer; entt::registry registry; clazz instance; organizer.emplace<&ro_int_double>("before"); organizer.emplace<&sync_point>("sync_1"); organizer.emplace<&clazz::ro_int_char_double>(instance, "mid_1"); organizer.emplace<&ro_int_double>("mid_2"); organizer.emplace<&sync_point>("sync_2"); organizer.emplace<&ro_int_double>("after"); const auto graph = organizer.graph(); ASSERT_EQ(graph.size(), 6u); ASSERT_STREQ(graph[0u].name(), "before"); ASSERT_STREQ(graph[1u].name(), "sync_1"); ASSERT_STREQ(graph[2u].name(), "mid_1"); ASSERT_STREQ(graph[3u].name(), "mid_2"); ASSERT_STREQ(graph[4u].name(), "sync_2"); ASSERT_STREQ(graph[5u].name(), "after"); ASSERT_TRUE(graph[0u].top_level()); ASSERT_FALSE(graph[1u].top_level()); ASSERT_FALSE(graph[2u].top_level()); ASSERT_FALSE(graph[3u].top_level()); ASSERT_FALSE(graph[4u].top_level()); ASSERT_FALSE(graph[5u].top_level()); ASSERT_EQ(graph[0u].children().size(), 1u); ASSERT_EQ(graph[1u].children().size(), 2u); ASSERT_EQ(graph[2u].children().size(), 1u); ASSERT_EQ(graph[3u].children().size(), 1u); ASSERT_EQ(graph[4u].children().size(), 1u); ASSERT_EQ(graph[5u].children().size(), 0u); ASSERT_EQ(graph[0u].children()[0u], 1u); ASSERT_EQ(graph[1u].children()[0u], 2u); ASSERT_EQ(graph[1u].children()[1u], 3u); ASSERT_EQ(graph[2u].children()[0u], 4u); ASSERT_EQ(graph[3u].children()[0u], 4u); ASSERT_EQ(graph[4u].children()[0u], 5u); for(auto &&vertex: graph) { ASSERT_NO_FATAL_FAILURE(vertex.callback()(vertex.data(), registry)); } } TEST(Organizer, Override) { entt::organizer organizer; organizer.emplace<&ro_int_rw_char_double, const char, const double>("t1"); organizer.emplace<&ro_char_rw_double, const double>("t2"); organizer.emplace<&ro_int_double, double>("t3"); const auto graph = organizer.graph(); ASSERT_EQ(graph.size(), 3u); ASSERT_STREQ(graph[0u].name(), "t1"); ASSERT_STREQ(graph[1u].name(), "t2"); ASSERT_STREQ(graph[2u].name(), "t3"); ASSERT_TRUE(graph[0u].top_level()); ASSERT_TRUE(graph[1u].top_level()); ASSERT_FALSE(graph[2u].top_level()); ASSERT_EQ(graph[0u].children().size(), 1u); ASSERT_EQ(graph[1u].children().size(), 1u); ASSERT_EQ(graph[2u].children().size(), 0u); ASSERT_EQ(graph[0u].children()[0u], 2u); ASSERT_EQ(graph[1u].children()[0u], 2u); } TEST(Organizer, Prepare) { entt::organizer organizer; entt::registry registry; clazz instance; organizer.emplace<&ro_int_double>(); organizer.emplace<&clazz::rw_int_char>(instance); const auto graph = organizer.graph(); ASSERT_FALSE(registry.ctx().contains()); ASSERT_FALSE(registry.ctx().contains()); ASSERT_FALSE(registry.ctx().contains()); for(auto &&vertex: graph) { vertex.prepare(registry); } ASSERT_FALSE(registry.ctx().contains()); ASSERT_FALSE(registry.ctx().contains()); ASSERT_TRUE(registry.ctx().contains()); } TEST(Organizer, Dependencies) { entt::organizer organizer; clazz instance; organizer.emplace<&ro_int_double>(); organizer.emplace<&clazz::rw_int_char>(instance); organizer.emplace(+[](const void *, entt::registry &) {}); const auto graph = organizer.graph(); const entt::type_info *buffer[5u]{}; ASSERT_EQ(graph.size(), 3u); ASSERT_EQ(graph[0u].ro_count(), 2u); ASSERT_EQ(graph[0u].rw_count(), 0u); ASSERT_EQ(graph[0u].ro_dependency(buffer, 0u), 0u); ASSERT_EQ(graph[0u].rw_dependency(buffer, 2u), 0u); ASSERT_EQ(graph[0u].ro_dependency(buffer, 5u), 2u); ASSERT_EQ(*buffer[0u], entt::type_id()); ASSERT_EQ(*buffer[1u], entt::type_id()); ASSERT_EQ(graph[1u].ro_count(), 0u); ASSERT_EQ(graph[1u].rw_count(), 2u); ASSERT_EQ(graph[1u].ro_dependency(buffer, 2u), 0u); ASSERT_EQ(graph[1u].rw_dependency(buffer, 0u), 0u); ASSERT_EQ(graph[1u].rw_dependency(buffer, 5u), 2u); ASSERT_EQ(*buffer[0u], entt::type_id()); ASSERT_EQ(*buffer[1u], entt::type_id()); ASSERT_EQ(graph[2u].ro_count(), 1u); ASSERT_EQ(graph[2u].rw_count(), 1u); ASSERT_EQ(graph[2u].ro_dependency(buffer, 2u), 1u); ASSERT_EQ(graph[2u].rw_dependency(buffer, 0u), 0u); ASSERT_EQ(graph[2u].ro_dependency(buffer, 5u), 1u); ASSERT_EQ(*buffer[0u], entt::type_id()); ASSERT_EQ(graph[2u].rw_dependency(buffer, 5u), 1u); ASSERT_EQ(*buffer[0u], entt::type_id()); } TEST(Organizer, ToArgsIntegrity) { entt::organizer organizer; entt::registry registry; organizer.emplace<&to_args_integrity>(); registry.ctx().emplace(42u); auto graph = organizer.graph(); graph[0u].callback()(graph[0u].data(), registry); ASSERT_EQ(registry.ctx().at(), 0u); }