psemek/libs/ecs/tests/apply.cpp

263 lines
6.1 KiB
C++

#include <psemek/test/test.hpp>
#include <psemek/ecs/entity_container.hpp>
#include <psemek/ecs/declare_uuid.hpp>
#include <psemek/random/generator.hpp>
#include <psemek/random/uniform.hpp>
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)
{
entity_container container;
int const count = 2048;
for (int i = 0; i < count; ++i)
container.create();
int call_count = 0;
container.apply<>([&](entity_container &, entity_handle const &){ ++call_count; });
container.apply<>([&](entity_container &){ ++call_count; });
container.apply<>([&](entity_handle const &){ ++call_count; });
container.apply<>([&]{ ++call_count; });
expect_equal(count * 4, call_count);
}
test_case(ecs_apply_components_1)
{
entity_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>([&](component_1 const & component){
++count;
sum += component.value;
});
expect_equal(count, expected_count);
expect_equal(sum, expected_sum);
}
test_case(ecs_apply_components_2)
{
entity_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>([&](component_1 const & component){
++count;
sum += component.value;
});
container.apply<component_2>([&](component_2 const & component){
++count;
sum += component.value;
});
container.apply<component_1, component_2>([&](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_batch_invoke)
{
entity_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<component_1>([&](entity_container &, util::span<entity_handle const>, util::span<component_1> components){ call_count += components.size(); });
container.batch_apply<component_1>([&](entity_container &, util::span<component_1> components){ call_count += components.size(); });
container.batch_apply<component_1>([&](util::span<entity_handle const>, util::span<component_1> components){ call_count += components.size(); });
container.batch_apply<component_1>([&](util::span<component_1> components){ call_count += components.size(); });
expect_equal(count * 4, call_count);
}
test_case(ecs_apply_batch_components)
{
entity_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<component_1>([&](util::span<component_1 const> components){
count += components.size();
for (auto & component : components)
sum += component.value;
});
container.batch_apply<component_2>([&](util::span<component_2 const> components){
count += components.size();
for (auto & component : components)
sum += component.value;
});
container.batch_apply<component_1, component_2>([&](util::span<component_1 const> components1, util::span<component_2 const>){
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)
{
entity_container container;
std::vector<entity_handle> 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)
{
entity_container container;
std::vector<entity_handle> 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)
{
entity_container container;
random::generator rng;
std::vector<entity_handle> 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)
{
entity_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);
}