Skip to content

Commit

Permalink
Fixed entity id clearing, Added tests
Browse files Browse the repository at this point in the history
  • Loading branch information
gsnook committed Sep 28, 2024
1 parent d5a4356 commit 023f5f6
Show file tree
Hide file tree
Showing 5 changed files with 265 additions and 4 deletions.
2 changes: 1 addition & 1 deletion distr/flecs.c
Original file line number Diff line number Diff line change
Expand Up @@ -37041,7 +37041,7 @@ void ecs_table_clear_entities(
bool notify,
bool deallocate)
{
flecs_table_fini_data(world, table, notify, false, true, deallocate);
flecs_table_fini_data(world, table, notify, true, true, deallocate);
}

/* Cleanup, no OnRemove, clear entity index, deactivate table, free allocations */
Expand Down
2 changes: 1 addition & 1 deletion src/storage/table.c
Original file line number Diff line number Diff line change
Expand Up @@ -963,7 +963,7 @@ void ecs_table_clear_entities(
bool notify,
bool deallocate)
{
flecs_table_fini_data(world, table, notify, false, true, deallocate);
flecs_table_fini_data(world, table, notify, true, true, deallocate);
}

/* Cleanup, no OnRemove, clear entity index, deactivate table, free allocations */
Expand Down
8 changes: 7 additions & 1 deletion test/core/project.json
Original file line number Diff line number Diff line change
Expand Up @@ -2296,7 +2296,13 @@
"has_id",
"has_pair",
"has_wildcard_pair",
"has_any_pair"
"has_any_pair",
"clear_table_kills_entities",
"clear_table_add_new",
"clear_table_check_size",
"clear_table_twice_check_size",
"clear_table_on_remove_hooks",
"clear_table_on_remove_observer"
]
}, {
"id": "Poly",
Expand Down
225 changes: 225 additions & 0 deletions test/core/src/Table.c
Original file line number Diff line number Diff line change
Expand Up @@ -617,3 +617,228 @@ void Table_has_any_pair(void) {

ecs_fini(world);
}

static
void Clear_table_and_verify_members_not_alive(bool notify, bool dealloc) {
ecs_world_t *world = ecs_mini();

ECS_COMPONENT(world, Position);

ecs_entity_t e1 = ecs_new(world);
ecs_add(world, e1, Position);
ecs_entity_t e2 = ecs_new(world);
ecs_add(world, e2, Position);

ecs_table_t *table = ecs_get_table(world, e1);

ecs_table_clear_entities(world, table, notify, dealloc);

test_assert(!ecs_is_alive(world, e1));
test_assert(!ecs_is_alive(world, e2));
test_int(0, ecs_table_count(table));

ecs_fini(world);
}

void Table_clear_table_kills_entities(void) {
Clear_table_and_verify_members_not_alive(true, true);
Clear_table_and_verify_members_not_alive(false, true);
Clear_table_and_verify_members_not_alive(true, false);
Clear_table_and_verify_members_not_alive(false, false);
}

static
void Clear_table_and_verify_new_members_exist(bool notify, bool dealloc) {
ecs_world_t *world = ecs_mini();

ecs_entity_t ecs_id(Position) = ecs_component(world, {
.entity = ecs_new(world),
.type.size = ECS_SIZEOF(Position),
.type.alignment = ECS_ALIGNOF(Position)
});

ecs_entity_t e1 = ecs_new(world);
ecs_add(world, e1, Position);
ecs_entity_t e2 = ecs_new(world);
ecs_add(world, e2, Position);

ecs_table_t *table = ecs_get_table(world, e1);

ecs_table_clear_entities(world, table, notify, dealloc);

ecs_id(Position) = ecs_component(world, {
.entity = ecs_new(world),
.type.size = ECS_SIZEOF(Position),
.type.alignment = ECS_ALIGNOF(Position)
});

ecs_entity_t e3 = ecs_new(world);
ecs_add(world, e3, Position);
ecs_entity_t e4 = ecs_new(world);
ecs_add(world, e4, Position);
test_assert(ecs_is_alive(world, e3));
test_assert(ecs_is_alive(world, e4));

ecs_table_t *table_e3 = ecs_get_table(world, e3);
ecs_table_t *table_e4 = ecs_get_table(world, e4);

test_assert(table_e3 == table_e4);
test_int(2, ecs_table_count(table_e3));

ecs_fini(world);
}

void Table_clear_table_add_new(void) {
Clear_table_and_verify_new_members_exist(true, true);
Clear_table_and_verify_new_members_exist(false, true);
Clear_table_and_verify_new_members_exist(true, false);
Clear_table_and_verify_new_members_exist(false, false);
}

static
void Clear_table_and_check_size(bool notify, bool dealloc) {
ecs_world_t *world = ecs_mini();

ECS_COMPONENT(world, Position);

ecs_entity_t e1 = ecs_new(world);
ecs_add(world, e1, Position);
ecs_entity_t e2 = ecs_new(world);
ecs_add(world, e2, Position);

ecs_table_t *table = ecs_get_table(world, e1);
const int32_t size = ecs_table_size(table);

ecs_table_clear_entities(world, table, notify, dealloc);

const int32_t expected_size = dealloc ? 0 : size;
test_int(expected_size, ecs_table_size(table));
test_int(0, ecs_table_count(table));

ecs_fini(world);
}

void Table_clear_table_check_size(void) {
Clear_table_and_check_size(true, true);
Clear_table_and_check_size(false, true);
Clear_table_and_check_size(true, false);
Clear_table_and_check_size(false, false);
}

static
void Clear_table_twice_and_check_size(bool first_dealloc, bool second_dealloc) {
ecs_world_t *world = ecs_mini();

ECS_COMPONENT(world, Position);

ecs_entity_t e1 = ecs_new(world);
ecs_add(world, e1, Position);
ecs_entity_t e2 = ecs_new(world);
ecs_add(world, e2, Position);

ecs_table_t *table = ecs_get_table(world, e1);
const int32_t size = ecs_table_size(table);

ecs_table_clear_entities(world, table, true, first_dealloc);
ecs_table_clear_entities(world, table, true, second_dealloc);

const int32_t expected_size = (first_dealloc || second_dealloc) ? 0 : size;
test_int(expected_size, ecs_table_size(table));
test_int(0, ecs_table_count(table));

ecs_fini(world);
}

void Table_clear_table_twice_check_size(void) {
Clear_table_twice_and_check_size(true, true);
Clear_table_twice_and_check_size(false, true);
Clear_table_twice_and_check_size(true, false);
Clear_table_twice_and_check_size(false, false);
}

static int on_remove_position = 0;

static void ecs_on_remove(Position)(ecs_iter_t *it) {
test_assert(it->count >= 1);
test_assert(it->event == EcsOnRemove);

Position *p = ecs_field(it, Position, 0);
for (int i = 0; i < it->count; i ++) {
on_remove_position ++;
test_int(p[i].x, 10);
test_int(p[i].y, 20);
}
}

static
void Verify_on_remove_hooks_table_clear(bool notify, bool dealloc) {
ecs_world_t *world = ecs_mini();
on_remove_position = 0;

ECS_COMPONENT(world, Position);

ecs_set_hooks(world, Position, {
.on_remove = ecs_on_remove(Position)
});

ecs_entity_t e1 = ecs_insert(world, ecs_value(Position, {10, 20}));
ecs_entity_t e2 = ecs_insert(world, ecs_value(Position, {10, 20}));
ecs_entity_t e3 = ecs_insert(world, ecs_value(Position, {10, 20}));

ecs_table_t *table = ecs_get_table(world, e1);
ecs_table_clear_entities(world, table, notify, dealloc);

test_int(on_remove_position, 3);

ecs_fini(world);
}

void Table_clear_table_on_remove_hooks(void) {
Verify_on_remove_hooks_table_clear(true, true);
Verify_on_remove_hooks_table_clear(false, true);
Verify_on_remove_hooks_table_clear(true, false);
Verify_on_remove_hooks_table_clear(false, false);
}

static
void Observer(ecs_iter_t *it) {
probe_system_w_ctx(it, it->ctx);
}

static
void Check_on_remove_when_clearing_table(bool notify, bool dealloc) {
ecs_world_t *world = ecs_mini();

ECS_COMPONENT(world, Position);

Probe ctx = {0};
ecs_entity_t o = ecs_observer(world, {
.query.terms = {{EcsWildcard}},
.events = {EcsOnRemove},
.callback = Observer,
.ctx = &ctx
});
test_assert(o != 0);

ecs_entity_t e1 = ecs_new(world);
ecs_add(world, e1, Position);
ecs_entity_t e2 = ecs_new(world);
ecs_add(world, e2, Position);

test_int(ctx.invoked, 0);

ecs_table_t *table = ecs_get_table(world, e1);
ecs_table_clear_entities(world, table, notify, dealloc);

test_int(ctx.invoked, notify ? 1 : 0);
test_int(ctx.count, notify ? 2 : 0);

ecs_fini(world);
}

void Table_clear_table_on_remove_observer(void) {
Check_on_remove_when_clearing_table(true, true);
Check_on_remove_when_clearing_table(false, true);
Check_on_remove_when_clearing_table(true, false);
Check_on_remove_when_clearing_table(false, false);
}
32 changes: 31 additions & 1 deletion test/core/src/main.c
Original file line number Diff line number Diff line change
Expand Up @@ -2210,6 +2210,12 @@ void Table_has_id(void);
void Table_has_pair(void);
void Table_has_wildcard_pair(void);
void Table_has_any_pair(void);
void Table_clear_table_kills_entities(void);
void Table_clear_table_add_new(void);
void Table_clear_table_check_size(void);
void Table_clear_table_twice_check_size(void);
void Table_clear_table_on_remove_hooks(void);
void Table_clear_table_on_remove_observer(void);

// Testsuite 'Poly'
void Poly_on_set_poly_observer(void);
Expand Down Expand Up @@ -10803,6 +10809,30 @@ bake_test_case Table_testcases[] = {
{
"has_any_pair",
Table_has_any_pair
},
{
"clear_table_kills_entities",
Table_clear_table_kills_entities
},
{
"clear_table_add_new",
Table_clear_table_add_new
},
{
"clear_table_check_size",
Table_clear_table_check_size
},
{
"clear_table_twice_check_size",
Table_clear_table_twice_check_size
},
{
"clear_table_on_remove_hooks",
Table_clear_table_on_remove_hooks
},
{
"clear_table_on_remove_observer",
Table_clear_table_on_remove_observer
}
};

Expand Down Expand Up @@ -11251,7 +11281,7 @@ static bake_test_suite suites[] = {
"Table",
NULL,
NULL,
24,
30,
Table_testcases
},
{
Expand Down

0 comments on commit 023f5f6

Please sign in to comment.