#include #include #include #include #include using namespace psemek; using namespace psemek::ecs; namespace { struct component_1 { int value; psemek_ecs_declare_uuid("component_1") }; struct component_2 { int value; psemek_ecs_declare_uuid("component_2") }; void check_impl(entity_container & container, int count0, int count1, int count2, int count12) { int call_count = 0; container.apply<>([&]{ ++call_count; }); expect_equal(call_count, count0 + count1 + count2 + count12); call_count = 0; container.apply([&](component_1 const &){ ++call_count; }); expect_equal(call_count, count1 + count12); call_count = 0; container.apply([&](component_2 const &){ ++call_count; }); expect_equal(call_count, count2 + count12); call_count = 0; container.apply([&](component_1 const &, component_2 const &){ ++call_count; }); expect_equal(call_count, count12); } } test_case(ecs_attach_empty) { entity_container container; auto h = container.create(); expect(container.get(h).get_if() == nullptr); expect(container.get(h).get_if() == nullptr); check_impl(container, 1, 0, 0, 0); } test_case(ecs_attach_one) { entity_container container; auto h = container.create(); container.attach(h, component_1{10}); expect_equal(container.get(h).get().value, 10); expect(container.get(h).get_if() == nullptr); check_impl(container, 0, 1, 0, 0); } test_case(ecs_attach_twice) { entity_container container; auto h = container.create(); container.attach(h, component_1{10}); container.attach(h, component_1{11}); expect_equal(container.get(h).get().value, 11); expect(container.get(h).get_if() == nullptr); check_impl(container, 0, 1, 0, 0); } test_case(ecs_attach_two) { entity_container container; auto h = container.create(); container.attach(h, component_1{10}); container.attach(h, component_2{20}); expect_equal(container.get(h).get().value, 10); expect_equal(container.get(h).get().value, 20); check_impl(container, 0, 0, 0, 1); } test_case(ecs_detach_empty) { entity_container container; auto h = container.create(); container.detach(h); expect(container.get(h).get_if() == nullptr); expect(container.get(h).get_if() == nullptr); check_impl(container, 1, 0, 0, 0); } test_case(ecs_detach_nonexistent) { entity_container container; auto h = container.create(component_1{10}); container.detach(h); expect_equal(container.get(h).get().value, 10); expect(container.get(h).get_if() == nullptr); check_impl(container, 0, 1, 0, 0); } test_case(ecs_detach_one) { entity_container container; auto h = container.create(component_1{10}, component_2{20}); container.detach(h); expect_equal(container.get(h).get().value, 10); expect(container.get(h).get_if() == nullptr); check_impl(container, 0, 1, 0, 0); } test_case(ecs_detach_two) { entity_container container; auto h = container.create(component_1{10}, component_2{20}); container.detach(h); container.detach(h); expect(container.get(h).get_if() == nullptr); expect(container.get(h).get_if() == nullptr); check_impl(container, 1, 0, 0, 0); } test_case(ecs_attach_random) { random::generator rng; entity_container container; int count0 = 0; int count1 = 0; int count2 = 0; int count12 = 0; for (int i = 0; i < 1024 * 1024; ++i) { auto h = container.create(); bool has1 = random::uniform(rng); bool has2 = random::uniform(rng); if (has1 && has2) { container.attach(h, component_1{i}, component_2{2 * i}); ++count12; } else if (has1 && !has2) { container.attach(h, component_1{i}); ++count1; } else if (!has1 && has2) { container.attach(h, component_2{2 * i}); ++count2; } else { ++count0; } } check_impl(container, count0, count1, count2, count12); } test_case(ecs_detach_random) { random::generator rng; entity_container container; int count0 = 0; int count1 = 0; int count2 = 0; int count12 = 0; for (int i = 0; i < 1024 * 1024; ++i) { auto h = container.create(component_1{i}, component_2{2 * i}); bool has1 = random::uniform(rng); bool has2 = random::uniform(rng); if (has1 && has2) { ++count12; } else if (has1 && !has2) { container.detach(h); ++count1; } else if (!has1 && has2) { container.detach(h); ++count2; } else { container.detach(h); ++count0; } } check_impl(container, count0, count1, count2, count12); }