#include #include namespace { using namespace psemek::util; struct test_component_1 { int species_value_1; struct data { int entity_value_1; }; }; struct test_component_2 { int species_value_2; struct data { int entity_value_2; }; }; struct test_behavior_1 : ecs::behavior { int call_count = 0; int value_sum = 0; void operator()(test_component_1::data & c) { call_count += 1; value_sum += c.entity_value_1; } }; struct test_behavior_12 : ecs::behavior { int call_count = 0; int value_sum_1 = 0; int value_sum_2 = 0; void operator()(test_component_1::data & c1, test_component_2::data & c2) { call_count += 1; value_sum_1 += c1.entity_value_1; value_sum_2 += c2.entity_value_2; } }; struct test_behavior_species_12 : ecs::behavior { int expected_value_1; int expected_value_2; int call_count = 0; void operator()(test_component_1::data &, test_component_2::data &, context const & ctx) { expect_equal(ctx.get().species_value_1, expected_value_1); expect_equal(ctx.get().species_value_2, expected_value_2); ++call_count; } }; } test_case(util_ecs_species__impl_sparse_component) { using namespace psemek::util::ecs_detail; psemek::util::ecs ecs; sparse_species_impl species(&ecs, "species 1", 0, test_component_1{10}); expect_different_ptr(species.get_species_component(), nullptr); expect_equal(species.get_species_component()->species_value_1, 10); expect_equal_ptr(species.get_species_component(), nullptr); sparse_species_impl species_2(&ecs, "species 2", 1, test_component_2{20}); expect_equal_ptr(species_2.get_species_component(), nullptr); expect_different_ptr(species_2.get_species_component(), nullptr); expect_equal(species_2.get_species_component()->species_value_2, 20); sparse_species_impl species_12(&ecs, "species 12", 2, test_component_1{100}, test_component_2{200}); expect_different_ptr(species_12.get_species_component(), nullptr); expect_equal(species_12.get_species_component()->species_value_1, 100); expect_different_ptr(species_12.get_species_component(), nullptr); expect_equal(species_12.get_species_component()->species_value_2, 200); } test_case(util_ecs_species__impl_packed_component) { using namespace psemek::util::ecs_detail; psemek::util::ecs ecs; packed_species_impl species(&ecs, "species 1", 0, test_component_1{10}); expect_different_ptr(species.get_species_component(), nullptr); expect_equal(species.get_species_component()->species_value_1, 10); expect_equal_ptr(species.get_species_component(), nullptr); packed_species_impl species_2(&ecs, "species 2", 1, test_component_2{20}); expect_equal_ptr(species_2.get_species_component(), nullptr); expect_different_ptr(species_2.get_species_component(), nullptr); expect_equal(species_2.get_species_component()->species_value_2, 20); packed_species_impl species_12(&ecs, "species 12", 2, test_component_1{100}, test_component_2{200}); expect_different_ptr(species_12.get_species_component(), nullptr); expect_equal(species_12.get_species_component()->species_value_1, 100); expect_different_ptr(species_12.get_species_component(), nullptr); expect_equal(species_12.get_species_component()->species_value_2, 200); } test_case(util_ecs_species__impl_sparse_entity) { using namespace psemek::util::ecs_detail; psemek::util::ecs ecs; sparse_species_impl species(&ecs, "species", 0, test_component_1{10}); expect_equal(species.entity_count(), 0); int const N = 10; for (std::size_t i = 0; i < N; ++i) species.add_entity(); expect_equal(species.entity_count(), N); test_component_1::data * cptr_1 = species.get_entity_component(); expect_different(cptr_1, nullptr); for (std::size_t i = 0; i < N; ++i) cptr_1[i].entity_value_1 = i; for (std::size_t i = 0; i < N; ++i) species.add_entity(); expect_equal(species.entity_count(), 2 * N); cptr_1 = species.get_entity_component(); expect_different(cptr_1, nullptr); for (std::size_t i = 0; i < N; ++i) expect_equal(cptr_1[i].entity_value_1, i); } test_case(util_ecs_species__impl_packed_entity) { using namespace psemek::util::ecs_detail; psemek::util::ecs ecs; packed_species_impl species(&ecs, "species", 0, test_component_1{10}); expect_equal(species.entity_count(), 0); int const N = 10; for (std::size_t i = 0; i < N; ++i) species.add_entity(); expect_equal(species.entity_count(), N); test_component_1::data * cptr_1 = species.get_entity_component(); expect_different(cptr_1, nullptr); for (std::size_t i = 0; i < N; ++i) cptr_1[i].entity_value_1 = i; for (std::size_t i = 0; i < N; ++i) species.add_entity(); expect_equal(species.entity_count(), 2 * N); cptr_1 = species.get_entity_component(); expect_different(cptr_1, nullptr); for (std::size_t i = 0; i < N; ++i) expect_equal(cptr_1[i].entity_value_1, i); } test_case(util_ecs_entity_sparse) { using namespace psemek; util::ecs ecs; auto species = ecs.register_species("species", util::ecs::policy::sparse, test_component_1{10}); expect_equal(ecs.entity_count(species), 0); auto entity = ecs.add_entity(species); ecs.get(entity).entity_value_1 = 100; expect_equal(ecs.get(entity).entity_value_1, 100); expect_throw(ecs.get(entity), std::exception); } test_case(util_ecs_entity_packed) { using namespace psemek; util::ecs ecs; auto species = ecs.register_species("species", util::ecs::policy::packed, test_component_1{10}); expect_equal(ecs.entity_count(species), 0); auto entity = ecs.add_entity(species); ecs.get(entity).entity_value_1 = 100; expect_equal(ecs.get(entity).entity_value_1, 100); expect_throw(ecs.get(entity), std::exception); } test_case(util_ecs_behavior_1_sparse) { using namespace psemek; util::ecs ecs; auto species = ecs.register_species("species", util::ecs::policy::sparse, test_component_1{10}); expect_equal(ecs.entity_count(species), 0); int N = 100; for (int i = 0; i < N; ++i) { auto entity = ecs.add_entity(species); ecs.get(entity).entity_value_1 = i; } test_behavior_1 behavior_1; ecs.apply(behavior_1); expect_equal(behavior_1.call_count, N); expect_equal(behavior_1.value_sum, (N * (N - 1)) / 2); test_behavior_12 behavior_12; ecs.apply(behavior_12); expect_equal(behavior_12.call_count, 0); expect_equal(behavior_12.value_sum_1, 0); expect_equal(behavior_12.value_sum_2, 0); } test_case(util_ecs_behavior_1_packed) { using namespace psemek; util::ecs ecs; auto species = ecs.register_species("species", util::ecs::policy::packed, test_component_1{10}); expect_equal(ecs.entity_count(species), 0); int N = 100; for (int i = 0; i < N; ++i) { auto entity = ecs.add_entity(species); ecs.get(entity).entity_value_1 = i; } test_behavior_1 behavior_1; ecs.apply(behavior_1); expect_equal(behavior_1.call_count, N); expect_equal(behavior_1.value_sum, (N * (N - 1)) / 2); test_behavior_12 behavior_12; ecs.apply(behavior_12); expect_equal(behavior_12.call_count, 0); expect_equal(behavior_12.value_sum_1, 0); expect_equal(behavior_12.value_sum_2, 0); } test_case(util_ecs_behavior_1__2_sparse) { using namespace psemek; util::ecs ecs; auto species_1 = ecs.register_species("species 1", util::ecs::policy::sparse, test_component_1{10}); auto species_2 = ecs.register_species("species 2", util::ecs::policy::sparse, test_component_2{20}); int N = 100; for (int i = 0; i < N; ++i) { auto entity = ecs.add_entity(species_1); ecs.get(entity).entity_value_1 = i; } for (int i = 0; i < N; ++i) { auto entity = ecs.add_entity(species_2); ecs.get(entity).entity_value_2 = -i; } test_behavior_1 behavior; ecs.apply(behavior); expect_equal(behavior.call_count, N); expect_equal(behavior.value_sum, (N * (N - 1)) / 2); test_behavior_12 behavior_12; ecs.apply(behavior_12); expect_equal(behavior_12.call_count, 0); expect_equal(behavior_12.value_sum_1, 0); expect_equal(behavior_12.value_sum_2, 0); } test_case(util_ecs_behavior_1__2_packed) { using namespace psemek; util::ecs ecs; auto species_1 = ecs.register_species("species 1", util::ecs::policy::packed, test_component_1{10}); auto species_2 = ecs.register_species("species 2", util::ecs::policy::packed, test_component_2{20}); int N = 100; for (int i = 0; i < N; ++i) { auto entity = ecs.add_entity(species_1); ecs.get(entity).entity_value_1 = i; } for (int i = 0; i < N; ++i) { auto entity = ecs.add_entity(species_2); ecs.get(entity).entity_value_2 = -i; } test_behavior_1 behavior; ecs.apply(behavior); expect_equal(behavior.call_count, N); expect_equal(behavior.value_sum, (N * (N - 1)) / 2); test_behavior_12 behavior_12; ecs.apply(behavior_12); expect_equal(behavior_12.call_count, 0); expect_equal(behavior_12.value_sum_1, 0); expect_equal(behavior_12.value_sum_2, 0); } test_case(util_ecs_behavior_12_sparse) { using namespace psemek; util::ecs ecs; auto species = ecs.register_species("species", util::ecs::policy::sparse, test_component_1{10}, test_component_2{20}); int N = 100; for (int i = 0; i < N; ++i) { auto entity = ecs.add_entity(species); ecs.get(entity).entity_value_1 = i; ecs.get(entity).entity_value_2 = -i; } test_behavior_1 behavior; ecs.apply(behavior); expect_equal(behavior.call_count, N); expect_equal(behavior.value_sum, (N * (N - 1)) / 2); test_behavior_12 behavior_12; ecs.apply(behavior_12); expect_equal(behavior_12.call_count, N); expect_equal(behavior_12.value_sum_1, (N * (N - 1)) / 2); expect_equal(behavior_12.value_sum_2, - (N * (N - 1)) / 2); } test_case(util_ecs_behavior_12_packed) { using namespace psemek; util::ecs ecs; auto species = ecs.register_species("species", util::ecs::policy::packed, test_component_1{10}, test_component_2{20}); int N = 100; for (int i = 0; i < N; ++i) { auto entity = ecs.add_entity(species); ecs.get(entity).entity_value_1 = i; ecs.get(entity).entity_value_2 = -i; } test_behavior_1 behavior; ecs.apply(behavior); expect_equal(behavior.call_count, N); expect_equal(behavior.value_sum, (N * (N - 1)) / 2); test_behavior_12 behavior_12; ecs.apply(behavior_12); expect_equal(behavior_12.call_count, N); expect_equal(behavior_12.value_sum_1, (N * (N - 1)) / 2); expect_equal(behavior_12.value_sum_2, - (N * (N - 1)) / 2); } test_case(util_ecs_behavior_species_sparse) { using namespace psemek; util::ecs ecs; auto species = ecs.register_species("species", util::ecs::policy::sparse, test_component_1{10}, test_component_2{20}); int N = 100; for (int i = 0; i < N; ++i) { auto entity = ecs.add_entity(species); ecs.get(entity).entity_value_1 = 0; ecs.get(entity).entity_value_2 = 0; } test_behavior_species_12 behavior; behavior.expected_value_1 = 10; behavior.expected_value_2 = 20; ecs.apply(behavior); expect_equal(behavior.call_count, N); } test_case(util_ecs_behavior_species_packed) { using namespace psemek; util::ecs ecs; auto species = ecs.register_species("species", util::ecs::policy::packed, test_component_1{10}, test_component_2{20}); int N = 100; for (int i = 0; i < N; ++i) { auto entity = ecs.add_entity(species); ecs.get(entity).entity_value_1 = 0; ecs.get(entity).entity_value_2 = 0; } test_behavior_species_12 behavior; behavior.expected_value_1 = 10; behavior.expected_value_2 = 20; ecs.apply(behavior); expect_equal(behavior.call_count, N); }