Files
PixelDefense/engine/libs/flecs/test/api/src/Delete.c

755 lines
17 KiB
C

#include <api.h>
void Delete_setup(void) {
ecs_log_set_level(-3);
}
void Delete_delete_1(void) {
ecs_world_t *world = ecs_mini();
ECS_COMPONENT(world, Position);
ecs_entity_t e = ecs_new(world, Position);
test_assert(e != 0);
ecs_delete(world, e);
test_assert(ecs_exists(world, e));
test_assert(!ecs_is_alive(world, e));
ecs_fini(world);
}
void Delete_delete_1_again(void) {
ecs_world_t *world = ecs_mini();
ECS_COMPONENT(world, Position);
ecs_entity_t e = ecs_new(world, Position);
test_assert(e != 0);
ecs_delete(world, e);
test_assert(ecs_exists(world, e));
test_assert(!ecs_is_alive(world, e));
ecs_delete(world, e);
test_assert(ecs_exists(world, e));
test_assert(!ecs_is_alive(world, e));
ecs_fini(world);
}
void Delete_delete_recycled_tag_again(void) {
ecs_world_t *world = ecs_mini();
ecs_entity_t e = ecs_new_id(world);
test_assert(e != 0);
ecs_delete(world, e);
test_assert(ecs_exists(world, e));
test_assert(!ecs_is_alive(world, e));
ecs_entity_t t = ecs_new_id(world);
test_assert(t != 0);
test_assert((uint32_t)t == (uint32_t)e);
test_assert(ecs_exists(world, e));
test_assert(!ecs_is_alive(world, e));
test_assert(ecs_exists(world, t));
test_assert(ecs_is_alive(world, t));
ecs_entity_t f = ecs_new_id(world);
ecs_add_id(world, f, t);
ecs_delete(world, e);
test_assert(ecs_exists(world, e));
test_assert(!ecs_is_alive(world, e));
test_assert(ecs_exists(world, t));
test_assert(ecs_is_alive(world, t));
test_assert(ecs_has_id(world, f, t));
ecs_fini(world);
}
void Delete_delete_empty(void) {
ecs_world_t *world = ecs_mini();
ECS_COMPONENT(world, Position);
ecs_entity_t e = ecs_new(world, 0);
test_assert(e != 0);
ecs_delete(world, e);
test_assert(ecs_exists(world, e));
test_assert(!ecs_is_alive(world, e));
ecs_fini(world);
}
void Delete_delete_nonexist(void) {
ecs_world_t *world = ecs_mini();
ecs_delete(world, 100);
test_assert(!ecs_exists(world, 100));
test_assert(!ecs_is_alive(world, 100));
ecs_fini(world);
}
void Delete_delete_1st_of_3(void) {
ecs_world_t *world = ecs_mini();
ECS_COMPONENT(world, Position);
ecs_entity_t e1 = ecs_new(world, Position);
ecs_entity_t e2 = ecs_new(world, Position);
ecs_entity_t e3 = ecs_new(world, Position);
test_assert(e1 != 0);
test_assert(e2 != 0);
test_assert(e3 != 0);
ecs_delete(world, e1);
test_assert(ecs_exists(world, e1));
test_assert(!ecs_is_alive(world, e1));
test_assert(ecs_exists(world, e2));
test_assert(ecs_is_alive(world, e2));
test_assert(ecs_exists(world, e3));
test_assert(ecs_is_alive(world, e3));
ecs_fini(world);
}
void Delete_delete_2nd_of_3(void) {
ecs_world_t *world = ecs_mini();
ECS_COMPONENT(world, Position);
ecs_entity_t e1 = ecs_new(world, Position);
ecs_entity_t e2 = ecs_new(world, Position);
ecs_entity_t e3 = ecs_new(world, Position);
test_assert(e1 != 0);
test_assert(e2 != 0);
test_assert(e3 != 0);
ecs_delete(world, e2);
test_assert(ecs_exists(world, e1));
test_assert(ecs_is_alive(world, e1));
test_assert(ecs_exists(world, e2));
test_assert(!ecs_is_alive(world, e2));
test_assert(ecs_exists(world, e3));
test_assert(ecs_is_alive(world, e3));
ecs_fini(world);
}
void Delete_delete_3rd_of_3(void) {
ecs_world_t *world = ecs_mini();
ECS_COMPONENT(world, Position);
ecs_entity_t e1 = ecs_new(world, Position);
ecs_entity_t e2 = ecs_new(world, Position);
ecs_entity_t e3 = ecs_new(world, Position);
test_assert(e1 != 0);
test_assert(e2 != 0);
test_assert(e3 != 0);
ecs_delete(world, e3);
test_assert(ecs_exists(world, e1));
test_assert(ecs_is_alive(world, e1));
test_assert(ecs_exists(world, e2));
test_assert(ecs_is_alive(world, e2));
test_assert(ecs_exists(world, e3));
test_assert(!ecs_is_alive(world, e3));
ecs_fini(world);
}
void Delete_delete_2_of_3(void) {
ecs_world_t *world = ecs_mini();
ECS_COMPONENT(world, Position);
ecs_entity_t e1 = ecs_new(world, Position);
ecs_entity_t e2 = ecs_new(world, Position);
ecs_entity_t e3 = ecs_new(world, Position);
test_assert(e1 != 0);
test_assert(e2 != 0);
test_assert(e3 != 0);
ecs_delete(world, e2);
ecs_delete(world, e3);
test_assert(ecs_exists(world, e1));
test_assert(ecs_is_alive(world, e1));
test_assert(ecs_exists(world, e2));
test_assert(!ecs_is_alive(world, e2));
test_assert(ecs_exists(world, e3));
test_assert(!ecs_is_alive(world, e3));
ecs_fini(world);
}
void Delete_delete_3_of_3(void) {
ecs_world_t *world = ecs_mini();
ECS_COMPONENT(world, Position);
ecs_entity_t e1 = ecs_new(world, Position);
ecs_entity_t e2 = ecs_new(world, Position);
ecs_entity_t e3 = ecs_new(world, Position);
test_assert(e1 != 0);
test_assert(e2 != 0);
test_assert(e3 != 0);
ecs_delete(world, e1);
ecs_delete(world, e2);
ecs_delete(world, e3);
test_assert(ecs_exists(world, e1));
test_assert(!ecs_is_alive(world, e1));
test_assert(ecs_exists(world, e2));
test_assert(!ecs_is_alive(world, e2));
test_assert(ecs_exists(world, e3));
test_assert(!ecs_is_alive(world, e3));
ecs_fini(world);
}
static
void CreateEntity(ecs_iter_t *it) {
ecs_id_t ecs_id(Position) = ecs_field_id(it, 1);
const ecs_entity_t *ids = ecs_bulk_new(it->world, Position, 10);
test_assert(ids != NULL);
}
static
void DeleteEntity(ecs_iter_t *it) {
int i;
for (i = 0; i < it->count; i ++) {
ecs_delete(it->world, it->entities[i]);
}
}
static int on_remove_system_invoked;
static
void OnRemoveSystem(ecs_iter_t *it) {
int i;
for (i = 0; i < it->count; i ++) {
on_remove_system_invoked ++;
}
}
void Delete_delete_w_on_remove(void) {
ecs_world_t *world = ecs_init();
ECS_COMPONENT(world, Position);
ECS_SYSTEM(world, CreateEntity, EcsOnUpdate, [out] Position());
ECS_SYSTEM(world, DeleteEntity, EcsOnStore, Position);
ECS_OBSERVER(world, OnRemoveSystem, EcsOnRemove, Position);
ecs_progress(world, 0);
test_int( ecs_count(world, Position), 0);
test_int(on_remove_system_invoked, 10);
ecs_fini(world);
}
void Delete_clear_1_component(void) {
ecs_world_t *world = ecs_mini();
ECS_COMPONENT(world, Position);
ecs_entity_t e = ecs_new(world, Position);
test_assert(e != 0);
ecs_clear(world, e);
test_assert(!ecs_get_type(world, e));
ecs_entity_t e2 = ecs_new(world, 0);
test_assert(e2 > e);
ecs_fini(world);
}
void Delete_clear_2_components(void) {
ecs_world_t *world = ecs_mini();
ECS_COMPONENT(world, Position);
ECS_COMPONENT(world, Velocity);
ecs_entity_t e = ecs_new(world, Position);
ecs_add(world, e, Velocity);
test_assert(e != 0);
ecs_clear(world, e);
test_assert(!ecs_get_type(world, e));
ecs_entity_t e2 = ecs_new(world, 0);
test_assert(e2 > e);
ecs_fini(world);
}
void Delete_alive_after_delete(void) {
ecs_world_t *world = ecs_mini();
ECS_COMPONENT(world, Position);
ecs_entity_t e = ecs_new(world, Position);
test_assert(e != 0);
test_assert(ecs_is_alive(world, e));
ecs_delete(world, e);
test_assert(!ecs_is_alive(world, e));
test_assert(ecs_exists(world, e));
ecs_fini(world);
}
void Delete_alive_after_clear(void) {
ecs_world_t *world = ecs_mini();
ECS_COMPONENT(world, Position);
ecs_entity_t e = ecs_new(world, Position);
test_assert(e != 0);
test_assert(ecs_is_alive(world, e));
ecs_clear(world, e);
test_assert(!ecs_get_type(world, e));
test_assert(ecs_is_alive(world, e));
test_assert(ecs_exists(world, e));
ecs_fini(world);
}
void Delete_alive_after_staged_delete(void) {
ecs_world_t *world = ecs_mini();
ECS_COMPONENT(world, Position);
ecs_entity_t e = ecs_new(world, Position);
test_assert(e != 0);
test_assert(ecs_is_alive(world, e));
ecs_defer_begin(world);
ecs_delete(world, e);
ecs_defer_end(world);
test_assert(ecs_exists(world, e));
test_assert(!ecs_is_alive(world, e));
ecs_fini(world);
}
void Delete_alive_while_staged(void) {
ecs_world_t *world = ecs_mini();
ECS_COMPONENT(world, Position);
ecs_entity_t e = ecs_new(world, Position);
test_assert(e != 0);
test_assert(ecs_is_alive(world, e));
ecs_defer_begin(world);
test_assert(ecs_is_alive(world, e));
ecs_defer_end(world);
ecs_fini(world);
}
void Delete_alive_while_staged_w_delete(void) {
ecs_world_t *world = ecs_mini();
ECS_COMPONENT(world, Position);
ecs_entity_t e = ecs_new(world, Position);
test_assert(e != 0);
test_assert(ecs_is_alive(world, e));
ecs_defer_begin(world);
test_assert(ecs_is_alive(world, e));
ecs_delete(world, e);
test_assert(ecs_is_alive(world, e));
ecs_defer_end(world);
test_assert(!ecs_is_alive(world, e));
test_assert(ecs_exists(world, e));
ecs_fini(world);
}
void Delete_alive_while_staged_w_delete_recycled_id(void) {
ecs_world_t *world = ecs_mini();
ECS_COMPONENT(world, Position);
ecs_entity_t e = ecs_new(world, Position);
test_assert(e != 0);
test_assert(ecs_is_alive(world, e));
ecs_delete(world, e);
e = ecs_new(world, 0);
test_assert(ecs_is_alive(world, e));
ecs_defer_begin(world);
test_assert(ecs_is_alive(world, e));
ecs_delete(world, e);
test_assert(ecs_is_alive(world, e));
ecs_defer_end(world);
test_assert(!ecs_is_alive(world, e));
test_assert(ecs_exists(world, e));
ecs_fini(world);
}
void Delete_alive_after_recycle(void) {
ecs_world_t *world = ecs_mini();
ECS_COMPONENT(world, Position);
ecs_entity_t e = ecs_new(world, Position);
test_assert(e != 0);
test_assert(ecs_is_alive(world, e));
ecs_delete(world, e);
test_assert(!ecs_is_alive(world, e));
test_assert(ecs_exists(world, e));
ecs_entity_t e2 = ecs_new(world, 0);
test_assert(e2 != 0);
test_assert(ecs_is_alive(world, e2));
test_assert(e != e2);
test_assert((ECS_ENTITY_MASK & e) == (ECS_ENTITY_MASK & e2));
ecs_fini(world);
}
void Delete_delete_recycled(void) {
ecs_world_t *world = ecs_mini();
ecs_entity_t e = ecs_new(world, 0);
ecs_delete(world, e);
test_assert(!ecs_is_alive(world, e));
test_assert(ecs_exists(world, e));
ecs_entity_t e2 = ecs_new(world, 0);
test_assert(e != e2);
test_assert((e2 & ECS_ENTITY_MASK) == (e & ECS_ENTITY_MASK));
test_assert(!ecs_is_alive(world, e));
test_assert(ecs_is_alive(world, e2));
ecs_delete(world, e);
test_assert(!ecs_is_alive(world, e));
test_assert(ecs_is_alive(world, e2));
ecs_fini(world);
}
void Delete_get_alive_for_alive(void) {
ecs_world_t *world = ecs_mini();
ecs_entity_t e = ecs_new(world, 0);
test_assert(e != 0);
test_assert(ecs_is_alive(world, e));
test_assert(ecs_exists(world, e));
ecs_entity_t a = ecs_get_alive(world, e);
test_assert(a != 0);
test_assert(e == a);
ecs_fini(world);
}
void Delete_get_alive_for_recycled(void) {
ecs_world_t *world = ecs_mini();
ecs_entity_t e = ecs_new(world, 0);
test_assert(e != 0);
ecs_delete(world, e);
test_assert(!ecs_is_alive(world, e));
test_assert(ecs_exists(world, e));
e = ecs_new(world, 0);
test_assert(ecs_entity_t_lo(e) != e); // Ensure id is recycled
ecs_entity_t a = ecs_get_alive(world, ecs_entity_t_lo(e));
test_assert(a != 0);
test_assert(e == a);
ecs_fini(world);
}
void Delete_get_alive_for_not_alive(void) {
ecs_world_t *world = ecs_mini();
ecs_entity_t e = ecs_new(world, 0);
test_assert(e != 0);
ecs_delete(world, e);
test_assert(!ecs_is_alive(world, e));
test_assert(ecs_exists(world, e));
// Ensure id has no generation
test_assert(ecs_entity_t_lo(e) == e);
ecs_entity_t a = ecs_get_alive(world, e);
test_assert(a == 0);
ecs_fini(world);
}
void Delete_get_alive_w_generation_for_recycled_alive(void) {
ecs_world_t *world = ecs_mini();
ecs_entity_t e = ecs_new(world, 0);
test_assert(e != 0);
ecs_delete(world, e);
test_assert(!ecs_is_alive(world, e));
test_assert(ecs_exists(world, e));
e = ecs_new(world, 0);
test_assert(ecs_entity_t_lo(e) != e);
ecs_entity_t a = ecs_get_alive(world, e);
test_assert(a != 0);
test_assert(e == a);
ecs_fini(world);
}
void Delete_get_alive_w_generation_for_recycled_not_alive(void) {
ecs_world_t *world = ecs_mini();
ecs_entity_t e = ecs_new(world, 0);
test_assert(e != 0);
ecs_delete(world, e);
test_assert(!ecs_is_alive(world, e));
test_assert(ecs_exists(world, e));
e = ecs_new(world, 0);
test_assert(ecs_entity_t_lo(e) != e);
ecs_delete(world, e);
test_assert(ecs_get_alive(world, e) == 0);
ecs_fini(world);
}
void Delete_get_alive_for_0(void) {
ecs_world_t *world = ecs_mini();
test_assert(0 == ecs_get_alive(world, 0));
ecs_fini(world);
}
void Delete_get_alive_for_nonexistent(void) {
ecs_world_t *world = ecs_mini();
ecs_entity_t e = ecs_get_alive(world, 1000);
test_assert(e == 0);
ecs_fini(world);
}
static int move_invoked = 0;
static int dtor_invoked = 0;
static int dtor_x;
static int dtor_y;
static int move_dst_x;
static int move_dst_y;
static int move_src_x;
static int move_src_y;
static ECS_DTOR(Position, ptr, {
dtor_invoked ++;
dtor_x = ptr->x;
dtor_y = ptr->y;
})
static ECS_MOVE(Position, dst, src, {
move_dst_x = dst->x;
move_dst_y = dst->y;
move_src_x = src->x;
move_src_y = src->y;
*dst = *src;
move_invoked ++;
})
void Delete_move_w_dtor_move(void) {
ecs_world_t *world = ecs_mini();
ECS_COMPONENT(world, Position);
ecs_set_hooks(world, Position, {
.dtor = ecs_dtor(Position),
.move = ecs_move(Position),
});
ecs_entity_t e_1 = ecs_new_id(world);
test_assert(e_1 != 0);
ecs_entity_t e_2 = ecs_new_id(world);
test_assert(e_2 != 0);
ecs_set(world, e_1, Position, {10, 20});
ecs_set(world, e_2, Position, {30, 40}); // append after e_1
test_int(move_invoked, 0);
ecs_delete(world, e_1); // move e_2 to e_1
test_assert(!ecs_is_alive(world, e_1));
test_assert(ecs_is_alive(world, e_2));
// counter intuitive, but this is because in this case the move is
// responsible for cleaning up e_1, because e_2 is moved into e_1
test_int(dtor_invoked, 1);
test_int(dtor_x, 30);
test_int(dtor_y, 40);
test_int(move_invoked, 1);
test_int(move_dst_x, 10);
test_int(move_dst_y, 20);
test_int(move_src_x, 30);
test_int(move_src_y, 40);
const Position *p = ecs_get(world, e_2, Position);
test_assert(p != NULL);
test_int(p->x, 30);
test_int(p->y, 40);
ecs_fini(world);
}
void Delete_move_w_dtor_no_move(void) {
ecs_world_t *world = ecs_mini();
ECS_COMPONENT(world, Position);
ecs_set_hooks(world, Position, {
.dtor = ecs_dtor(Position)
});
ecs_entity_t e_1 = ecs_new_id(world);
test_assert(e_1 != 0);
ecs_entity_t e_2 = ecs_new_id(world);
test_assert(e_2 != 0);
ecs_set(world, e_1, Position, {10, 20});
ecs_set(world, e_2, Position, {30, 40}); // append after e_1
ecs_delete(world, e_1); // move e_2 to e_1
test_assert(!ecs_is_alive(world, e_1));
test_assert(ecs_is_alive(world, e_2));
test_int(dtor_invoked, 1);
test_int(dtor_x, 10);
test_int(dtor_y, 20);
const Position *p = ecs_get(world, e_2, Position);
test_assert(p != NULL);
test_int(p->x, 30);
test_int(p->y, 40);
ecs_fini(world);
}
void Delete_move_w_no_dtor_move(void) {
ecs_world_t *world = ecs_mini();
ECS_COMPONENT(world, Position);
ecs_set_hooks(world, Position, {
.move = ecs_move(Position)
});
ecs_entity_t e_1 = ecs_new_id(world);
test_assert(e_1 != 0);
ecs_entity_t e_2 = ecs_new_id(world);
test_assert(e_2 != 0);
ecs_set(world, e_1, Position, {10, 20});
ecs_set(world, e_2, Position, {30, 40}); // append after e_1
ecs_delete(world, e_1); // move e_2 to e_1
test_assert(!ecs_is_alive(world, e_1));
test_assert(ecs_is_alive(world, e_2));
test_int(move_invoked, 1);
test_int(move_dst_x, 10);
test_int(move_dst_y, 20);
test_int(move_src_x, 30);
test_int(move_src_y, 40);
const Position *p = ecs_get(world, e_2, Position);
test_assert(p != NULL);
test_int(p->x, 30);
test_int(p->y, 40);
ecs_fini(world);
}
void Delete_wrap_generation_count(void) {
ecs_world_t *world = ecs_mini();
ecs_entity_t start = ecs_new_id(world);
ecs_entity_t e = start;
for (int i = 0; i < 65535; i ++) {
ecs_delete(world, e);
e = ecs_new_id(world);
test_assert(e != start);
test_assert((uint32_t)e == start);
}
ecs_delete(world, e);
e = ecs_new_id(world);
test_assert(e == start);
for (int i = 0; i < 65535; i ++) {
ecs_delete(world, e);
e = ecs_new_id(world);
test_assert(e != start);
test_assert((uint32_t)e == start);
}
ecs_delete(world, e);
e = ecs_new_id(world);
test_assert(e == start);
ecs_fini(world);
}