263 lines
6 KiB
C++
263 lines
6 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 &, handle const &){ ++call_count; });
|
|
container.apply<>([&](entity_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)
|
|
{
|
|
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<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<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<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<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<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);
|
|
}
|