Skip to content

Commit

Permalink
test(ecs): check if relations are destroyed correctly
Browse files Browse the repository at this point in the history
  • Loading branch information
RiscadoA committed Jan 24, 2024
1 parent bb8faaa commit f736c20
Show file tree
Hide file tree
Showing 4 changed files with 84 additions and 3 deletions.
2 changes: 2 additions & 0 deletions core/src/cubos/core/ecs/types.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -39,11 +39,13 @@ void Types::add(const reflection::Type& type, Kind kind)

DataTypeId Types::id(const reflection::Type& type) const
{
CUBOS_ASSERT(mTypes.contains(type), "Type {} not registered", type.name());
return mTypes.at(type);
}

DataTypeId Types::id(const std::string& name) const
{
CUBOS_ASSERT(mNames.contains(name), "Type {} not registered", name);
return mNames.at(name);
}

Expand Down
6 changes: 3 additions & 3 deletions core/src/cubos/core/ecs/world.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -144,7 +144,7 @@ void World::relate(Entity from, Entity to, const reflection::Type& type, void* v
CUBOS_ASSERT(this->isAlive(to));

auto dataType = mTypes.id(type);
CUBOS_ASSERT(mTypes.isRelation(dataType));
CUBOS_ASSERT(mTypes.isRelation(dataType), "Type {} is not registered as a relation", type.name());

// Create a sparse relation table identifier from the archetypes of both entities.
auto fromArchetype = mEntityPool.archetype(from.index);
Expand Down Expand Up @@ -230,7 +230,7 @@ auto World::Components::end() -> Iterator
auto World::Components::add(const reflection::Type& type, void* value) -> Components&
{
auto typeId = mWorld.mTypes.id(type);
CUBOS_ASSERT(mWorld.mTypes.isComponent(typeId), "Type '{}' is not registered as a component", type.name());
CUBOS_ASSERT(mWorld.mTypes.isComponent(typeId), "Type {} is not registered as a component", type.name());
auto columnId = ColumnId::make(typeId);

auto oldArchetype = mWorld.mEntityPool.archetype(mEntity.index);
Expand Down Expand Up @@ -265,7 +265,7 @@ auto World::Components::add(const reflection::Type& type, void* value) -> Compon
auto World::Components::remove(const reflection::Type& type) -> Components&
{
auto typeId = mWorld.mTypes.id(type);
CUBOS_ASSERT(mWorld.mTypes.isComponent(typeId), "Type '{}' is not registered as a component", type.name());
CUBOS_ASSERT(mWorld.mTypes.isComponent(typeId), "Type {} is not registered as a component", type.name());
auto columnId = ColumnId::make(typeId);

// If the old archetype doesn't contain this component type, then we don't do anything.
Expand Down
3 changes: 3 additions & 0 deletions core/tests/ecs/utils.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -76,4 +76,7 @@ inline void setupWorld(cubos::core::ecs::World& world)
world.registerComponent<DetectDestructorComponent>();
world.registerComponent<EntityArrayComponent>();
world.registerComponent<EntityDictionaryComponent>();
world.registerRelation<EmptyRelation>();
world.registerRelation<IntegerRelation>();
world.registerRelation<DetectDestructorRelation>();
}
76 changes: 76 additions & 0 deletions core/tests/ecs/world.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -133,4 +133,80 @@ TEST_CASE("ecs::World")

CHECK(destroyed);
}

SUBCASE("add and remove relations")
{
// Create three entities.
auto foo = world.create();
auto bar = world.create();
auto baz = world.create();

bool fooBarFlag = false;
bool barBazFlag = false;
bool fooBazFlag = false;
bool fooFooFlag = false;

// Relate foo to bar.
REQUIRE_FALSE(world.related<DetectDestructorRelation>(foo, bar));
world.relate(foo, bar, DetectDestructorRelation{{&fooBarFlag}});
REQUIRE(world.related<DetectDestructorRelation>(foo, bar));

// Relate bar to baz.
REQUIRE_FALSE(world.related<DetectDestructorRelation>(bar, baz));
world.relate(bar, baz, DetectDestructorRelation{{&barBazFlag}});
REQUIRE(world.related<DetectDestructorRelation>(bar, baz));

// Relate foo to baz.
REQUIRE_FALSE(world.related<DetectDestructorRelation>(foo, baz));
world.relate(foo, baz, DetectDestructorRelation{{&fooBazFlag}});
REQUIRE(world.related<DetectDestructorRelation>(foo, baz));

// Relate foo to foo.
REQUIRE_FALSE(world.related<DetectDestructorRelation>(foo, foo));
world.relate(foo, foo, DetectDestructorRelation{{&fooFooFlag}});
REQUIRE(world.related<DetectDestructorRelation>(foo, foo));

// Nothing should have been destroyed yet.
CHECK_FALSE(fooBarFlag);
CHECK_FALSE(barBazFlag);
CHECK_FALSE(fooBazFlag);
CHECK_FALSE(fooFooFlag);

// Remove the relation between foo and bar and add it again.
world.unrelate<DetectDestructorRelation>(foo, bar);
CHECK(fooBarFlag);
CHECK_FALSE(barBazFlag);
CHECK_FALSE(fooBazFlag);
CHECK_FALSE(fooFooFlag);
fooBarFlag = false;
world.relate(foo, bar, DetectDestructorRelation{{&fooBarFlag}});

// Destroy bar.
world.destroy(bar);
CHECK(fooBarFlag);
CHECK(barBazFlag);
CHECK_FALSE(fooBazFlag);
CHECK_FALSE(fooFooFlag);

// Destroy foo.
world.destroy(foo);
CHECK(fooBazFlag);
CHECK(fooFooFlag);
}

SUBCASE("relations are correctly destructed when the world is destroyed")
{
bool destroyed = false;

// Create a world with an entity and a relation and immediately destroy it.
{
World world{};
setupWorld(world);
auto foo = world.create();
world.relate(foo, foo, DetectDestructorRelation{{&destroyed}});
CHECK_FALSE(destroyed);
}

CHECK(destroyed);
}
}

0 comments on commit f736c20

Please sign in to comment.