#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") }; } test_case(ecs_apply_empty) { container container; int const count = 2048; for (int i = 0; i < count; ++i) container.create(); int call_count = 0; container.apply<>([&](ecs::container &, handle const &){ ++call_count; }); container.apply<>([&](ecs::container &){ ++call_count; }); container.apply<>([&](handle const &){ ++call_count; }); container.apply<>([&]{ ++call_count; }); expect_equal(count * 4, call_count); } test_case(ecs_apply_components_1) { container container; random::generator rng; int const expected_count = 1024 * 1024; int expected_sum = 0; for (int i = 0; i < expected_count; ++i) { int value = random::uniform(rng, -1024, 1024); expected_sum += value; container.create(component_1{value}); } int count = 0; int sum = 0; container.apply([&](component_1 const & component){ ++count; sum += component.value; }); expect_equal(count, expected_count); expect_equal(sum, expected_sum); } test_case(ecs_apply_components_2) { container container; random::generator rng; int const expected_count = 1024*1024; int expected_sum = 0; for (int i = 0; i < expected_count; ++i) { int value = random::uniform(rng, -1024, 1024); int type = random::uniform(rng, 0, 2); if (type == 0) container.create(component_1{value}); else if (type == 1) container.create(component_2{value}); else if (type == 2) container.create(component_1{value}, component_2{value}); expected_sum += value; } int count = 0; int sum = 0; container.apply([&](component_1 const & component){ ++count; sum += component.value; }); container.apply([&](component_2 const & component){ ++count; sum += component.value; }); container.apply([&](component_1 const & component1, component_2 const &){ --count; sum -= component1.value; }); expect_equal(count, expected_count); expect_equal(sum, expected_sum); } test_case(ecs_apply_without) { container container; int const count = 1024; int call_count = 0; for (int i = 0; i < count; ++i) container.create(); call_count = 0; container.apply>([&]{ ++call_count; }); expect_equal(count, call_count); call_count = 0; container.apply>([&](component_1 const &){ ++call_count; }); expect_equal(0, call_count); for (int i = 0; i < count; ++i) container.create(component_1{i}); call_count = 0; container.apply>([&]{ ++call_count; }); expect_equal(count * 2, call_count); call_count = 0; container.apply>([&](component_1 const &){ ++call_count; }); expect_equal(count, call_count); for (int i = 0; i < count; ++i) container.create(component_2{i}); call_count = 0; container.apply>([&]{ ++call_count; }); expect_equal(count * 2, call_count); call_count = 0; container.apply>([&](component_1 const &){ ++call_count; }); expect_equal(count, call_count); for (int i = 0; i < count; ++i) container.create(component_1{i}, component_2{i}); call_count = 0; container.apply>([&]{ ++call_count; }); expect_equal(count * 2, call_count); call_count = 0; container.apply>([&](component_1 const &){ ++call_count; }); expect_equal(count, call_count); } test_case(ecs_apply_batch_invoke) { container container; int const count = 2048; for (int i = 0; i < count; ++i) container.create(component_1{i}); int call_count = 0; container.batch_apply([&](ecs::container &, util::span, util::span components){ call_count += components.size(); }); container.batch_apply([&](ecs::container &, util::span components){ call_count += components.size(); }); container.batch_apply([&](util::span, util::span components){ call_count += components.size(); }); container.batch_apply([&](util::span components){ call_count += components.size(); }); expect_equal(count * 4, call_count); } test_case(ecs_apply_batch_components) { container container; random::generator rng; int const expected_count = 1024*1024; int expected_sum = 0; for (int i = 0; i < expected_count; ++i) { int value = random::uniform(rng, -1024, 1024); int type = random::uniform(rng, 0, 2); if (type == 0) container.create(component_1{value}); else if (type == 1) container.create(component_2{value}); else if (type == 2) container.create(component_1{value}, component_2{value}); expected_sum += value; } int count = 0; int sum = 0; container.batch_apply([&](util::span components){ count += components.size(); for (auto & component : components) sum += component.value; }); container.batch_apply([&](util::span components){ count += components.size(); for (auto & component : components) sum += component.value; }); container.batch_apply([&](util::span components1, util::span){ count -= components1.size(); for (auto & component : components1) sum -= component.value; }); expect_equal(count, expected_count); expect_equal(sum, expected_sum); } test_case(ecs_apply_remove_forward) { container container; std::vector handles; int const count = 1024 * 1024; for (int i = 0; i < count; ++i) handles.push_back(container.create()); int call_count = 0; container.apply([&]{ ++call_count; if (call_count == count) for (auto h : handles) container.destroy(h); }); for (auto h : handles) expect(!container.alive(h)); } test_case(ecs_apply_remove_reversed) { container container; std::vector handles; int const count = 1024 * 1024; for (int i = 0; i < count; ++i) handles.push_back(container.create()); std::reverse(handles.begin(), handles.end()); int call_count = 0; container.apply([&]{ ++call_count; if (call_count == count) for (auto h : handles) container.destroy(h); }); expect_equal(call_count, call_count); for (auto h : handles) expect(!container.alive(h)); } test_case(ecs_apply_remove_random) { container container; random::generator rng; std::vector handles; int const count = 1024 * 1024; for (int i = 0; i < count; ++i) handles.push_back(container.create()); std::shuffle(handles.begin(), handles.end(), rng); int call_count = 0; container.apply([&]{ ++call_count; if (call_count == count) for (auto h : handles) container.destroy(h); }); expect_equal(call_count, call_count); for (auto h : handles) expect(!container.alive(h)); } test_case(ecs_apply_create) { container container; int const count = 1024 * 1024; for (int i = 0; i < count; ++i) container.create(); int call_count = 0; container.apply([&]{ ++call_count; container.create(); }); expect_equal(call_count, count); call_count = 0; container.apply([&]{ ++call_count; }); expect_equal(call_count, 2 * count); } test_case(ecs_apply_const) { container container; container.create(component_1{10}, component_2{20}); container.apply([](component_1 & value1, component_2 const & value2){ expect_equal(value1.value, 10); expect_equal(value2.value, 20); }); }