psemek/libs/ecs/tests/attach.cpp

242 lines
4.8 KiB
C++

#include <psemek/test/test.hpp>
#include <psemek/ecs/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")
};
void check_impl(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>([&](component_1 const &){ ++call_count; });
expect_equal(call_count, count1 + count12);
call_count = 0;
container.apply<component_2>([&](component_2 const &){ ++call_count; });
expect_equal(call_count, count2 + count12);
call_count = 0;
container.apply<component_1, component_2>([&](component_1 const &, component_2 const &){ ++call_count; });
expect_equal(call_count, count12);
}
}
test_case(ecs_attach_empty)
{
container container;
auto h = container.create();
expect(container.get(h).get_if<component_1>() == nullptr);
expect(container.get(h).get_if<component_2>() == nullptr);
check_impl(container, 1, 0, 0, 0);
}
test_case(ecs_attach_one)
{
container container;
auto h = container.create();
container.attach(h, component_1{10});
expect_equal(container.get(h).get<component_1>().value, 10);
expect(container.get(h).get_if<component_2>() == nullptr);
check_impl(container, 0, 1, 0, 0);
}
test_case(ecs_attach_twice)
{
container container;
auto h = container.create();
container.attach(h, component_1{10});
container.attach(h, component_1{11});
expect_equal(container.get(h).get<component_1>().value, 11);
expect(container.get(h).get_if<component_2>() == nullptr);
check_impl(container, 0, 1, 0, 0);
}
test_case(ecs_attach_two)
{
container container;
auto h = container.create();
container.attach(h, component_1{10});
container.attach(h, component_2{20});
expect_equal(container.get(h).get<component_1>().value, 10);
expect_equal(container.get(h).get<component_2>().value, 20);
check_impl(container, 0, 0, 0, 1);
}
test_case(ecs_detach_empty)
{
container container;
auto h = container.create();
container.detach<component_1>(h);
expect(container.get(h).get_if<component_1>() == nullptr);
expect(container.get(h).get_if<component_2>() == nullptr);
check_impl(container, 1, 0, 0, 0);
}
test_case(ecs_detach_nonexistent)
{
container container;
auto h = container.create(component_1{10});
container.detach<component_2>(h);
expect_equal(container.get(h).get<component_1>().value, 10);
expect(container.get(h).get_if<component_2>() == nullptr);
check_impl(container, 0, 1, 0, 0);
}
test_case(ecs_detach_one)
{
container container;
auto h = container.create(component_1{10}, component_2{20});
container.detach<component_2>(h);
expect_equal(container.get(h).get<component_1>().value, 10);
expect(container.get(h).get_if<component_2>() == nullptr);
check_impl(container, 0, 1, 0, 0);
}
test_case(ecs_detach_two)
{
container container;
auto h = container.create(component_1{10}, component_2{20});
container.detach<component_1>(h);
container.detach<component_2>(h);
expect(container.get(h).get_if<component_1>() == nullptr);
expect(container.get(h).get_if<component_2>() == nullptr);
check_impl(container, 1, 0, 0, 0);
}
test_case(ecs_attach_random)
{
random::generator rng;
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<bool>(rng);
bool has2 = random::uniform<bool>(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;
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<bool>(rng);
bool has2 = random::uniform<bool>(rng);
if (has1 && has2)
{
++count12;
}
else if (has1 && !has2)
{
container.detach<component_2>(h);
++count1;
}
else if (!has1 && has2)
{
container.detach<component_1>(h);
++count2;
}
else
{
container.detach<component_1, component_2>(h);
++count0;
}
}
check_impl(container, count0, count1, count2, count12);
}