Properly link flecs library

This commit is contained in:
2023-11-09 11:38:29 +01:00
parent dc585396c3
commit 8edcf9305c
1392 changed files with 390081 additions and 164 deletions

View File

@@ -0,0 +1,413 @@
#include <api.h>
#include <stdlib.h>
void Add_zero(void) {
install_test_abort();
ecs_world_t *world = ecs_mini();
ecs_entity_t e = ecs_new(world, 0);
test_assert(e != 0);
test_expect_abort();
ecs_add(world, e, 0);
}
void Add_component(void) {
ecs_world_t *world = ecs_mini();
ECS_COMPONENT(world, Position);
ecs_entity_t e = ecs_new(world, 0);
test_assert(e != 0);
ecs_add(world, e, Position);
test_assert(ecs_has(world, e, Position));
ecs_fini(world);
}
void Add_component_again(void) {
ecs_world_t *world = ecs_mini();
ECS_COMPONENT(world, Position);
ecs_entity_t e = ecs_new(world, 0);
test_assert(e != 0);
ecs_add(world, e, Position);
test_assert(ecs_has(world, e, Position));
ecs_add(world, e, Position);
test_assert(ecs_has(world, e, Position));
ecs_fini(world);
}
void Add_2_components(void) {
ecs_world_t *world = ecs_mini();
ECS_COMPONENT(world, Position);
ECS_COMPONENT(world, Velocity);
ecs_entity_t e = ecs_new(world, 0);
test_assert(e != 0);
ecs_add(world, e, Position);
test_assert(ecs_has(world, e, Position));
test_assert(!ecs_has(world, e, Velocity));
ecs_add(world, e, Velocity);
test_assert(ecs_has(world, e, Position));
test_assert(ecs_has(world, e, Velocity));
ecs_fini(world);
}
void Add_2_components_again(void) {
ecs_world_t *world = ecs_mini();
ECS_COMPONENT(world, Position);
ECS_COMPONENT(world, Velocity);
ecs_entity_t e = ecs_new(world, 0);
test_assert(e != 0);
ecs_add(world, e, Position);
ecs_add(world, e, Velocity);
test_assert(ecs_has(world, e, Position));
test_assert(ecs_has(world, e, Velocity));
ecs_add(world, e, Position);
ecs_add(world, e, Velocity);
test_assert(ecs_has(world, e, Position));
test_assert(ecs_has(world, e, Velocity));
ecs_fini(world);
}
void Add_2_components_overlap(void) {
ecs_world_t *world = ecs_mini();
ECS_COMPONENT(world, Position);
ECS_COMPONENT(world, Velocity);
ECS_COMPONENT(world, Mass);
ecs_entity_t e = ecs_new(world, 0);
test_assert(e != 0);
ecs_add(world, e, Position);
ecs_add(world, e, Velocity);
test_assert(ecs_has(world, e, Position));
test_assert(ecs_has(world, e, Velocity));
test_assert(!ecs_has(world, e, Mass));
ecs_add(world, e, Velocity);
ecs_add(world, e, Mass);
test_assert(ecs_has(world, e, Position));
test_assert(ecs_has(world, e, Velocity));
test_assert(ecs_has(world, e, Mass));
ecs_fini(world);
}
void Add_component_to_nonempty(void) {
ecs_world_t *world = ecs_mini();
ECS_COMPONENT(world, Position);
ECS_COMPONENT(world, Velocity);
ecs_entity_t e = ecs_new(world, Position);
test_assert(e != 0);
test_assert(ecs_has(world, e, Position));
ecs_add(world, e, Velocity);
test_assert(ecs_has(world, e, Position));
test_assert(ecs_has(world, e, Velocity));
ecs_fini(world);
}
void Add_component_to_nonempty_again(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_has(world, e, Position));
ecs_add(world, e, Position);
test_assert(ecs_has(world, e, Position));
ecs_fini(world);
}
void Add_component_to_nonempty_overlap(void) {
ecs_world_t *world = ecs_mini();
ECS_COMPONENT(world, Position);
ECS_COMPONENT(world, Velocity);
ECS_ENTITY(world, e, Position, Velocity);
test_assert(e != 0);
test_assert(ecs_has(world, e, Position));
test_assert(ecs_has(world, e, Velocity));
ecs_add(world, e, Position);
test_assert(ecs_has(world, e, Position));
test_assert(ecs_has(world, e, Velocity));
ecs_fini(world);
}
void Add_tag(void) {
ecs_world_t *world = ecs_mini();
ECS_ENTITY(world, Tag, 0);
ecs_entity_t e = ecs_new(world, 0);
test_assert(e != 0);
ecs_add_id(world, e, Tag);
test_assert(ecs_has_id(world, e, Tag));
ecs_fini(world);
}
void Add_add_entity(void) {
ecs_world_t *world = ecs_mini();
ecs_entity_t e = ecs_new(world, 0);
test_assert(e != 0);
ecs_entity_t f = ecs_new(world, 0);
test_assert(f != 0);
ecs_add_id(world, e, f);
test_assert(ecs_has_id(world, e, f));
ecs_fini(world);
}
void Add_remove_entity(void) {
ecs_world_t *world = ecs_mini();
ecs_entity_t e = ecs_new(world, 0);
test_assert(e != 0);
ecs_entity_t f = ecs_new(world, 0);
test_assert(f != 0);
ecs_add_id(world, e, f);
test_assert(ecs_has_id(world, e, f));
ecs_remove_id(world, e, f);
test_assert(!ecs_has_id(world, e, f));
ecs_fini(world);
}
void Add_add_0_entity(void) {
install_test_abort();
ecs_world_t *world = ecs_mini();
ecs_entity_t e = ecs_new(world, 0);
test_assert(e != 0);
test_expect_abort();
ecs_add_id(world, e, 0);
}
void Add_remove_0_entity(void) {
install_test_abort();
ecs_world_t *world = ecs_mini();
ECS_COMPONENT(world, Position);
ecs_entity_t e = ecs_new(world, Position);
test_assert(e != 0);
test_expect_abort();
ecs_remove_id(world, e, 0);
}
void Add_invalid_add_wildcard(void) {
install_test_abort();
ecs_world_t *world = ecs_mini();
ecs_entity_t e = ecs_new_id(world);
test_assert(e != 0);
test_expect_abort();
ecs_add_id(world, e, EcsWildcard);
}
void Add_invalid_add_pair_w_wildcard(void) {
install_test_abort();
ecs_world_t *world = ecs_mini();
ecs_entity_t e = ecs_new_id(world);
test_assert(e != 0);
test_expect_abort();
ecs_add_id(world, e, ecs_pair(EcsWildcard, EcsWildcard));
}
void Add_invalid_add_pair_w_wildcard_rel(void) {
install_test_abort();
ecs_world_t *world = ecs_mini();
ECS_TAG(world, Tag);
ecs_entity_t e = ecs_new_id(world);
test_assert(e != 0);
test_expect_abort();
ecs_add_id(world, e, ecs_pair(EcsWildcard, Tag));
}
void Add_invalid_add_pair_w_wildcard_obj(void) {
install_test_abort();
ecs_world_t *world = ecs_mini();
ECS_TAG(world, Tag);
ecs_entity_t e = ecs_new_id(world);
test_assert(e != 0);
test_expect_abort();
ecs_add_id(world, e, ecs_pair(Tag, EcsWildcard));
}
void Add_invalid_add_any(void) {
install_test_abort();
ecs_world_t *world = ecs_mini();
ECS_TAG(world, Tag);
ecs_entity_t e = ecs_new_id(world);
test_assert(e != 0);
test_expect_abort();
ecs_add_id(world, e, EcsAny);
}
void Add_invalid_add_pair_w_any(void) {
install_test_abort();
ecs_world_t *world = ecs_mini();
ECS_TAG(world, Tag);
ecs_entity_t e = ecs_new_id(world);
test_assert(e != 0);
test_expect_abort();
ecs_add_id(world, e, ecs_pair(EcsAny, EcsAny));
}
void Add_invalid_add_pair_w_any_rel(void) {
install_test_abort();
ecs_world_t *world = ecs_mini();
ECS_TAG(world, Tag);
ecs_entity_t e = ecs_new_id(world);
test_assert(e != 0);
test_expect_abort();
ecs_add_id(world, e, ecs_pair(EcsAny, Tag));
}
void Add_invalid_add_pair_w_any_obj(void) {
install_test_abort();
ecs_world_t *world = ecs_mini();
ECS_TAG(world, Tag);
ecs_entity_t e = ecs_new_id(world);
test_assert(e != 0);
test_expect_abort();
ecs_add_id(world, e, ecs_pair(Tag, EcsAny));
}
void Add_invalid_pair_w_0(void) {
install_test_abort();
ecs_world_t *world = ecs_mini();
ECS_TAG(world, Tag);
ecs_entity_t e = ecs_new_id(world);
test_assert(e != 0);
test_expect_abort();
ecs_add_id(world, e, ecs_pair(0, 0));
}
void Add_invalid_pair_w_0_rel(void) {
install_test_abort();
ecs_world_t *world = ecs_mini();
ECS_TAG(world, Tag);
ecs_entity_t e = ecs_new_id(world);
test_assert(e != 0);
test_expect_abort();
ecs_add_id(world, e, ecs_pair(0, Tag));
}
void Add_invalid_pair_w_0_obj(void) {
install_test_abort();
ecs_world_t *world = ecs_mini();
ECS_TAG(world, Tag);
ecs_entity_t e = ecs_new_id(world);
test_assert(e != 0);
test_expect_abort();
ecs_add_id(world, e, ecs_pair(Tag, 0));
}
void Add_add_random_id(void) {
ecs_world_t *world = ecs_mini();
for (int i = 0; i < 10; i ++) {
ecs_entity_t id = rand() % (100 * 1000) + 1000;
ecs_ensure(world, id);
test_assert(ecs_is_alive(world, id));
ecs_entity_t e = ecs_new_w_id(world, id);
test_assert(ecs_has_id(world, e, id));
}
ecs_fini(world);
}

View File

@@ -0,0 +1,350 @@
#include <api.h>
void Clone_empty(void) {
ecs_world_t *world = ecs_mini();
ecs_entity_t e1 = ecs_new(world, 0);
test_assert(e1 != 0);
ecs_entity_t e2 = ecs_clone(world, 0, e1, false);
test_assert(e2 != 0);
test_assert(e1 != e2);
test_assert(!ecs_get_type(world, e1));
test_assert(!ecs_get_type(world, e2));
ecs_fini(world);
}
void Clone_empty_w_value(void) {
ecs_world_t *world = ecs_mini();
ecs_entity_t e1 = ecs_new(world, 0);
test_assert(e1 != 0);
ecs_entity_t e2 = ecs_clone(world, 0, e1, true);
test_assert(e2 != 0);
test_assert(e1 != e2);
test_assert(!ecs_get_type(world, e1));
test_assert(!ecs_get_type(world, e2));
ecs_fini(world);
}
void Clone_null(void) {
install_test_abort();
ecs_world_t *world = ecs_mini();
test_expect_abort();
ecs_clone(world, 0, 0, false);
}
void Clone_null_w_value(void) {
install_test_abort();
ecs_world_t *world = ecs_mini();
test_expect_abort();
ecs_clone(world, 0, 0, true);
}
void Clone_1_component(void) {
ecs_world_t *world = ecs_mini();
ECS_COMPONENT(world, Position);
ecs_entity_t e1 = ecs_new(world, Position);
test_assert(e1 != 0);
ecs_entity_t e2 = ecs_clone(world, 0, e1, false);
test_assert(e2 != 0);
test_assert(e1 != e2);
test_assert(ecs_has(world, e1, Position));
test_assert(ecs_has(world, e2, Position));
test_assert(ecs_get(world, e1, Position) !=
ecs_get(world, e2, Position));
ecs_fini(world);
}
void Clone_2_component(void) {
ecs_world_t *world = ecs_mini();
ECS_COMPONENT(world, Position);
ECS_COMPONENT(world, Velocity);
ECS_ENTITY(world, e1, Position, Velocity);
test_assert(e1 != 0);
ecs_entity_t e2 = ecs_clone(world, 0, e1, false);
test_assert(e2 != 0);
test_assert(e1 != e2);
test_assert(ecs_has(world, e1, Position));
test_assert(ecs_has(world, e2, Position));
test_assert(ecs_get(world, e1, Position) !=
ecs_get(world, e2, Position));
test_assert(ecs_has(world, e1, Velocity));
test_assert(ecs_has(world, e2, Velocity));
test_assert(ecs_get(world, e1, Velocity) !=
ecs_get(world, e2, Velocity));
ecs_fini(world);
}
void Clone_3_component(void) {
ecs_world_t *world = ecs_mini();
ECS_COMPONENT(world, Position);
ECS_COMPONENT(world, Velocity);
ECS_COMPONENT(world, Mass);
ECS_ENTITY(world, e1, Position, Velocity, Mass);
test_assert(e1 != 0);
ecs_entity_t e2 = ecs_clone(world, 0, e1, false);
test_assert(e2 != 0);
test_assert(e1 != e2);
test_assert(ecs_has(world, e1, Position));
test_assert(ecs_has(world, e2, Position));
test_assert(ecs_get(world, e1, Position) !=
ecs_get(world, e2, Position));
test_assert(ecs_has(world, e1, Velocity));
test_assert(ecs_has(world, e2, Velocity));
test_assert(ecs_get(world, e1, Velocity) !=
ecs_get(world, e2, Velocity));
test_assert(ecs_has(world, e1, Mass));
test_assert(ecs_has(world, e2, Mass));
test_assert(ecs_get(world, e1, Mass) !=
ecs_get(world, e2, Mass));
ecs_fini(world);
}
void Clone_1_component_w_value(void) {
ecs_world_t *world = ecs_mini();
ECS_COMPONENT(world, Position);
ecs_entity_t e1 = ecs_new(world, 0);
test_assert(e1 != 0);
ecs_set(world, e1, Position, {10, 20});
ecs_entity_t e2 = ecs_clone(world, 0, e1, true);
test_assert(e2 != 0);
test_assert(e1 != e2);
test_assert(ecs_has(world, e1, Position));
test_assert(ecs_has(world, e2, Position));
const Position *p_1 = ecs_get(world, e1, Position);
test_assert(p_1 != NULL);
test_int(p_1->x, 10);
test_int(p_1->y, 20);
const Position *p_2 = ecs_get(world, e2, Position);
test_assert(p_2 != NULL);
test_assert(p_1 != p_2);
test_int(p_2->x, 10);
test_int(p_2->y, 20);
ecs_fini(world);
}
void Clone_2_component_w_value(void) {
ecs_world_t *world = ecs_mini();
ECS_COMPONENT(world, Position);
ECS_COMPONENT(world, Velocity);
ecs_entity_t e1 = ecs_new(world, 0);
test_assert(e1 != 0);
ecs_set(world, e1, Position, {10, 20});
ecs_set(world, e1, Velocity, {30, 40});
ecs_entity_t e2 = ecs_clone(world, 0, e1, true);
test_assert(e2 != 0);
test_assert(e1 != e2);
test_assert(ecs_has(world, e1, Position));
test_assert(ecs_has(world, e2, Position));
test_assert(ecs_has(world, e1, Velocity));
test_assert(ecs_has(world, e2, Velocity));
const Position *p_1 = ecs_get(world, e1, Position);
test_assert(p_1 != NULL);
test_int(p_1->x, 10);
test_int(p_1->y, 20);
const Position *p_2 = ecs_get(world, e2, Position);
test_assert(p_2 != NULL);
test_assert(p_1 != p_2);
test_int(p_2->x, 10);
test_int(p_2->y, 20);
const Velocity *v_1 = ecs_get(world, e1, Velocity);
test_assert(v_1 != NULL);
test_int(v_1->x, 30);
test_int(v_1->y, 40);
const Velocity *v_2 = ecs_get(world, e2, Velocity);
test_assert(v_2 != NULL);
test_assert(v_1 != v_2);
test_int(v_2->x, 30);
test_int(v_2->y, 40);
ecs_fini(world);
}
void Clone_3_component_w_value(void) {
ecs_world_t *world = ecs_mini();
ECS_COMPONENT(world, Position);
ECS_COMPONENT(world, Velocity);
ECS_COMPONENT(world, Mass);
ecs_entity_t e1 = ecs_new(world, 0);
test_assert(e1 != 0);
ecs_set(world, e1, Position, {10, 20});
ecs_set(world, e1, Velocity, {30, 40});
ecs_set(world, e1, Mass, {50});
ecs_entity_t e2 = ecs_clone(world, 0, e1, true);
test_assert(e2 != 0);
test_assert(e1 != e2);
test_assert(ecs_has(world, e1, Position));
test_assert(ecs_has(world, e2, Position));
test_assert(ecs_has(world, e1, Velocity));
test_assert(ecs_has(world, e2, Velocity));
test_assert(ecs_has(world, e1, Mass));
test_assert(ecs_has(world, e2, Mass));
const Position *p_1 = ecs_get(world, e1, Position);
test_assert(p_1 != NULL);
test_int(p_1->x, 10);
test_int(p_1->y, 20);
const Position *p_2 = ecs_get(world, e2, Position);
test_assert(p_2 != NULL);
test_assert(p_1 != p_2);
test_int(p_2->x, 10);
test_int(p_2->y, 20);
const Velocity *v_1 = ecs_get(world, e1, Velocity);
test_assert(v_1 != NULL);
test_int(v_1->x, 30);
test_int(v_1->y, 40);
const Velocity *v_2 = ecs_get(world, e2, Velocity);
test_assert(v_2 != NULL);
test_assert(v_1 != v_2);
test_int(v_2->x, 30);
test_int(v_2->y, 40);
const Mass *m_1 = ecs_get(world, e1, Mass);
test_assert(m_1 != NULL);
test_int(*m_1, 50);
const Mass *m_2 = ecs_get(world, e2, Mass);
test_assert(m_2 != NULL);
test_assert(m_1 != m_2);
test_int(*m_2, 50);
ecs_fini(world);
}
void Clone_tag(void) {
ecs_world_t *world = ecs_mini();
ECS_ENTITY(world, Tag, 0);
ecs_entity_t e1 = ecs_new_w_id(world, Tag);
test_assert(e1 != 0);
ecs_entity_t e2 = ecs_clone(world, 0, e1, false);
test_assert(e2 != 0);
test_assert(e1 != e2);
test_assert(ecs_has_id(world, e1, Tag));
test_assert(ecs_has_id(world, e2, Tag));
ecs_fini(world);
}
void Clone_tag_w_value(void) {
ecs_world_t *world = ecs_mini();
ECS_ENTITY(world, Tag, 0);
ecs_entity_t e1 = ecs_new_w_id(world, Tag);
test_assert(e1 != 0);
ecs_entity_t e2 = ecs_clone(world, 0, e1, true);
test_assert(e2 != 0);
test_assert(e1 != e2);
test_assert(ecs_has_id(world, e1, Tag));
test_assert(ecs_has_id(world, e2, Tag));
ecs_fini(world);
}
void Clone_1_tag_1_component(void) {
ecs_world_t *world = ecs_mini();
ECS_ENTITY(world, Tag, 0);
ECS_COMPONENT(world, Position);
ECS_ENTITY(world, e1, Position, Tag);
ecs_set(world, e1, Position, {10, 20});
ecs_entity_t e2 = ecs_clone(world, 0, e1, false);
test_assert(e2 != 0);
test_assert(e1 != e2);
test_assert(ecs_has_id(world, e1, Tag));
test_assert(ecs_has_id(world, e2, Tag));
test_assert(ecs_has(world, e1, Position));
test_assert(ecs_has(world, e2, Position));
ecs_fini(world);
}
void Clone_1_tag_1_component_w_value(void) {
ecs_world_t *world = ecs_mini();
ECS_ENTITY(world, Tag, 0);
ECS_COMPONENT(world, Position);
ecs_entity_t e1 = ecs_new_id(world);
ecs_add(world, e1, Tag);
ecs_set(world, e1, Position, {10, 20});
ecs_entity_t e2 = ecs_clone(world, 0, e1, true);
test_assert(e2 != 0);
test_assert(e1 != e2);
test_assert(ecs_has_id(world, e1, Tag));
test_assert(ecs_has_id(world, e2, Tag));
test_assert(ecs_has(world, e1, Position));
test_assert(ecs_has(world, e2, Position));
const Position *p = ecs_get(world, e2, Position);
test_assert(p != NULL);
test_int(p->x, 10);
test_int(p->y, 20);
ecs_fini(world);
}

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,64 @@
#include <api.h>
void Count_count_empty(void) {
ecs_world_t *world = ecs_mini();
test_int(ecs_count(world, 0), 0);
ecs_fini(world);
}
void Count_count_w_entity_0(void) {
ecs_world_t *world = ecs_mini();
test_int(ecs_count_id(world, 0), 0);
ecs_fini(world);
}
void Count_count_1_component(void) {
ecs_world_t *world = ecs_mini();
ECS_COMPONENT(world, Position);
ECS_ENTITY(world, e1, Position);
ECS_ENTITY(world, e2, Position);
test_int(ecs_count(world, Position), 2);
ecs_fini(world);
}
void Count_count_disabled(void) {
ecs_world_t *world = ecs_mini();
ECS_COMPONENT(world, Position);
ecs_entity_t e1 = ecs_new(world, Position);
ecs_new(world, Position);
test_int(ecs_count(world, Position), 2);
ecs_enable(world, e1, false);
test_int(ecs_count(world, Position), 2);
ecs_fini(world);
}
void Count_count_prefab(void) {
ecs_world_t *world = ecs_mini();
ECS_COMPONENT(world, Position);
ecs_entity_t e1 = ecs_new(world, Position);
ecs_new(world, Position);
test_int(ecs_count(world, Position), 2);
ecs_add_id(world, e1, EcsPrefab);
test_int(ecs_count(world, Position), 2);
ecs_fini(world);
}

View File

@@ -0,0 +1,754 @@
#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);
}

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,109 @@
#include <api.h>
#include <stdlib.h>
void Error_setup(void) {
ecs_os_set_api_defaults();
ecs_os_api_t os_api = ecs_os_api;
os_api.abort_ = test_abort;
ecs_os_set_api(&os_api);
ecs_log_set_level(-5);
}
void Error_abort(void) {
test_expect_abort();
ecs_abort(ECS_INTERNAL_ERROR, NULL);
}
void Error_abort_w_param(void) {
test_expect_abort();
ecs_abort(ECS_INTERNAL_ERROR, "some parameter");
}
static bool my_abort_called = false;
static
void my_abort(void) {
my_abort_called = true;
}
void Error_override_abort(void) {
/* The real reason this tests exists is to achieve 100% coverage. Without
* this test, the last line of the 'abort' function would never be covered
* because abort always exits before it gets there. */
/* hack, because the setup already set the OS API */
ecs_os_api.abort_ = my_abort;
ecs_os_abort();
test_assert(my_abort_called == true);
}
void Error_assert_true(void) {
ecs_assert(true, ECS_INTERNAL_ERROR, NULL);
/* Assert should not trigger */
test_assert(true);
}
void Error_assert_false(void) {
test_expect_abort();
ecs_assert(false, ECS_INTERNAL_ERROR, NULL);
/* Assert should not trigger */
test_assert(false);
}
void Error_assert_false_w_param(void) {
test_expect_abort();
ecs_assert(false, ECS_INTERNAL_ERROR, "some parameter");
/* Assert should not trigger */
test_assert(false);
}
void Error_error_codes(void) {
test_assert(ecs_strerror(ECS_INVALID_PARAMETER) != NULL);
test_assert(ecs_strerror(ECS_NOT_A_COMPONENT) != NULL);
test_assert(ecs_strerror(ECS_INTERNAL_ERROR) != NULL);
test_assert(ecs_strerror(ECS_ALREADY_DEFINED) != NULL);
test_assert(ecs_strerror(ECS_INVALID_COMPONENT_SIZE) != NULL);
test_assert(ecs_strerror(ECS_INVALID_COMPONENT_ALIGNMENT) != NULL);
test_assert(ecs_strerror(ECS_OUT_OF_MEMORY) != NULL);
test_assert(ecs_strerror(ECS_MODULE_UNDEFINED) != NULL);
test_assert(ecs_strerror(ECS_COLUMN_INDEX_OUT_OF_RANGE) != NULL);
test_assert(ecs_strerror(ECS_COLUMN_IS_NOT_SHARED) != NULL);
test_assert(ecs_strerror(ECS_COLUMN_IS_SHARED) != NULL);
test_assert(ecs_strerror(ECS_COLUMN_TYPE_MISMATCH) != NULL);
test_assert(ecs_strerror(ECS_INVALID_WHILE_READONLY) != NULL);
test_assert(ecs_strerror(ECS_INVALID_FROM_WORKER) != NULL);
test_assert(ecs_strerror(ECS_OUT_OF_RANGE) != NULL);
test_assert(ecs_strerror(ECS_OPERATION_FAILED) != NULL);
test_assert(ecs_strerror(ECS_MISSING_OS_API) != NULL);
test_assert(ecs_strerror(ECS_UNSUPPORTED) != NULL);
test_assert(ecs_strerror(ECS_ACCESS_VIOLATION) != NULL);
}
void Error_log_dbg(void) {
ecs_dbg("test debug message");
test_assert(true);
}
void Error_log_log(void) {
ecs_trace("test trace message");
test_assert(true);
}
void Error_log_warning(void) {
ecs_warn("test warning message");
test_assert(true);
}
void Error_log_error(void) {
ecs_err("test error message");
test_assert(true);
}
void Error_last_error(void) {
ecs_os_api.log_last_error_ = 10;
int err = ecs_log_last_error();
test_int(10, err);
test_int(0, ecs_log_last_error());
}

View File

@@ -0,0 +1,581 @@
#include <api.h>
static
void system_callback(ecs_iter_t *it) {
probe_iter(it);
}
void Event_table_1_id_w_trigger(void) {
ecs_world_t *world = ecs_mini();
ecs_entity_t evt = ecs_new_id(world);
ecs_entity_t id = ecs_new_id(world);
ecs_entity_t e = ecs_new_w_id(world, id);
ecs_table_t *table = ecs_get_table(world, e);
Probe ctx = {0};
ecs_entity_t s = ecs_observer_init(world, &(ecs_observer_desc_t){
.filter.terms[0].id = id,
.events = {evt},
.callback = system_callback,
.ctx = &ctx
});
ecs_emit(world, &(ecs_event_desc_t){
.event = evt,
.ids = &(ecs_type_t){.count = 1, .array = (ecs_id_t[]){ id }},
.table = table,
.observable = world
});
test_int(ctx.invoked, 1);
test_assert(ctx.system == s);
test_assert(ctx.event == evt);
test_assert(ctx.event_id == id);
test_int(ctx.count, 1);
test_assert(ctx.e[0] == e);
ecs_fini(world);
}
void Event_table_2_ids_w_trigger(void) {
ecs_world_t *world = ecs_mini();
ecs_entity_t evt = ecs_new_id(world);
ecs_entity_t id_a = ecs_new_id(world);
ecs_entity_t id_b = ecs_new_id(world);
ecs_entity_t e = ecs_new_w_id(world, id_a);
ecs_add_id(world, e, id_b);
ecs_table_t *table = ecs_get_table(world, e);
Probe ctx = {0};
ecs_entity_t s_a = ecs_observer_init(world, &(ecs_observer_desc_t){
.filter.terms[0].id = id_a,
.events = {evt},
.callback = system_callback,
.ctx = &ctx,
});
ecs_emit(world, &(ecs_event_desc_t){
.event = evt,
.ids = &(ecs_type_t){.count = 2, .array = (ecs_id_t[]){ id_a, id_b }},
.table = table,
.observable = world
});
test_int(ctx.invoked, 1);
test_assert(ctx.system == s_a);
test_assert(ctx.event == evt);
test_assert(ctx.event_id == id_a);
test_int(ctx.count, 1);
test_assert(ctx.e[0] == e);
ecs_delete(world, s_a);
ecs_entity_t s_b = ecs_observer_init(world, &(ecs_observer_desc_t){
.filter.terms[0].id = id_b,
.events = {evt},
.callback = system_callback,
.ctx = &ctx
});
ecs_os_zeromem(&ctx);
ecs_emit(world, &(ecs_event_desc_t){
.event = evt,
.ids = &(ecs_type_t){.count = 2, .array = (ecs_id_t[]){ id_a, id_b }},
.table = table,
.observable = world
});
test_int(ctx.invoked, 1);
test_assert(ctx.system == s_b);
test_assert(ctx.event == evt);
test_assert(ctx.event_id == id_b);
test_int(ctx.count, 1);
test_assert(ctx.e[0] == e);
ecs_fini(world);
}
void Event_table_1_id_w_observer(void) {
ecs_world_t *world = ecs_mini();
ecs_entity_t evt = ecs_new_id(world);
ecs_entity_t id = ecs_new_id(world);
ecs_entity_t e = ecs_new_w_id(world, id);
ecs_table_t *table = ecs_get_table(world, e);
Probe ctx = {0};
ecs_entity_t s = ecs_observer_init(world, &(ecs_observer_desc_t){
.filter.terms = {{ id }},
.events = {evt},
.callback = system_callback,
.ctx = &ctx
});
ecs_emit(world, &(ecs_event_desc_t){
.event = evt,
.ids = &(ecs_type_t){.count = 1, .array = (ecs_id_t[]){ id }},
.table = table,
.observable = world
});
test_int(ctx.invoked, 1);
test_assert(ctx.system == s);
test_assert(ctx.event == evt);
test_assert(ctx.event_id == id);
test_int(ctx.count, 1);
test_assert(ctx.e[0] == e);
ecs_fini(world);
}
void Event_table_2_ids_w_observer(void) {
ecs_world_t *world = ecs_mini();
ecs_entity_t evt = ecs_new_id(world);
ecs_entity_t id_a = ecs_new_id(world);
ecs_entity_t id_b = ecs_new_id(world);
ecs_entity_t e = ecs_new_w_id(world, id_a);
ecs_add_id(world, e, id_b);
ecs_table_t *table = ecs_get_table(world, e);
Probe ctx = {0};
ecs_entity_t s_a = ecs_observer_init(world, &(ecs_observer_desc_t){
.filter.terms = {{ id_a }},
.events = {evt},
.callback = system_callback,
.ctx = &ctx
});
ecs_emit(world, &(ecs_event_desc_t){
.event = evt,
.ids = &(ecs_type_t){.count = 2, .array = (ecs_id_t[]){ id_a, id_b }},
.table = table,
.observable = world
});
test_int(ctx.invoked, 1);
test_assert(ctx.system == s_a);
test_assert(ctx.event == evt);
test_assert(ctx.event_id == id_a || ctx.event_id == id_b);
test_int(ctx.count, 1);
test_assert(ctx.e[0] == e);
ecs_fini(world);
}
static int empty_table_callback_invoked = 0;
static
void empty_table_callback(ecs_iter_t *it) {
test_assert(it->table == it->ctx);
test_int(it->count, 0);
empty_table_callback_invoked++;
}
void Event_emit_event_for_empty_table(void) {
ecs_world_t *world = ecs_mini();
ECS_TAG(world, TagA);
ecs_entity_t evt = ecs_new_id(world);
ecs_entity_t e = ecs_new(world, TagA);
ecs_table_t *table = ecs_get_table(world, e);
ecs_delete(world, e);
ecs_entity_t o = ecs_observer_init(world, &(ecs_observer_desc_t){
.filter.terms = {{ TagA }},
.events = {evt},
.callback = empty_table_callback,
.ctx = table
});
ecs_emit(world, &(ecs_event_desc_t){
.event = evt,
.ids = &(ecs_type_t){.count = 1, .array = (ecs_id_t[]){ TagA }},
.table = table,
.observable = world
});
test_int(empty_table_callback_invoked, 1);
ecs_delete(world, o);
ecs_fini(world);
}
void Event_emit_table_event(void) {
ecs_world_t *world = ecs_mini();
ECS_TAG(world, TagA);
ecs_entity_t base = ecs_new_w_id(world, TagA);
ecs_table_t *base_table = ecs_get_table(world, base);
ecs_entity_t e = ecs_new_id(world);
ecs_add_pair(world, e, EcsIsA, base);
Probe ctx_a = {0};
Probe ctx_b = {0};
ecs_entity_t evt = ecs_new_id(world);
ecs_observer_init(world, &(ecs_observer_desc_t){
.filter.terms[0].id = TagA,
.filter.terms[0].src.flags = EcsSelf,
.events = {evt},
.callback = system_callback,
.ctx = &ctx_a
});
ecs_observer_init(world, &(ecs_observer_desc_t){
.filter.terms[0].id = TagA,
.filter.terms[0].src.flags = EcsUp,
.events = {evt},
.callback = system_callback,
.ctx = &ctx_b
});
ecs_emit(world, &(ecs_event_desc_t){
.event = evt,
.ids = &(ecs_type_t){.array = (ecs_id_t[]){ TagA }, .count = 1},
.table = base_table,
.observable = world
});
test_int(ctx_a.invoked, 1);
test_int(ctx_b.invoked, 1);
ecs_emit(world, &(ecs_event_desc_t){
.event = evt,
.ids = &(ecs_type_t){.array = (ecs_id_t[]){ TagA }, .count = 1},
.table = base_table,
.observable = world,
.flags = EcsEventTableOnly
});
test_int(ctx_a.invoked, 2);
test_int(ctx_b.invoked, 1);
ecs_fini(world);
}
void Event_emit_staged_from_world(void) {
ecs_world_t *world = ecs_mini();
ecs_entity_t evt = ecs_new_id(world);
ecs_entity_t id = ecs_new_id(world);
ecs_entity_t e = ecs_new_w_id(world, id);
ecs_table_t *table = ecs_get_table(world, e);
Probe ctx = {0};
ecs_entity_t s = ecs_observer_init(world, &(ecs_observer_desc_t){
.filter.terms[0].id = id,
.events = {evt},
.callback = system_callback,
.ctx = &ctx
});
ecs_readonly_begin(world);
ecs_emit(world, &(ecs_event_desc_t){
.event = evt,
.ids = &(ecs_type_t){.count = 1, .array = (ecs_id_t[]){ id }},
.table = table,
.observable = world
});
ecs_readonly_end(world);
test_int(ctx.invoked, 1);
test_assert(ctx.system == s);
test_assert(ctx.event == evt);
test_assert(ctx.event_id == id);
test_int(ctx.count, 1);
test_assert(ctx.e[0] == e);
ecs_fini(world);
}
void Event_emit_staged_from_stage(void) {
ecs_world_t *world = ecs_mini();
ecs_entity_t evt = ecs_new_id(world);
ecs_entity_t id = ecs_new_id(world);
ecs_entity_t e = ecs_new_w_id(world, id);
ecs_table_t *table = ecs_get_table(world, e);
Probe ctx = {0};
ecs_entity_t s = ecs_observer_init(world, &(ecs_observer_desc_t){
.filter.terms[0].id = id,
.events = {evt},
.callback = system_callback,
.ctx = &ctx
});
ecs_readonly_begin(world);
ecs_world_t *stage = ecs_get_stage(world, 0);
ecs_emit(stage, &(ecs_event_desc_t){
.event = evt,
.ids = &(ecs_type_t){.count = 1, .array = (ecs_id_t[]){ id }},
.table = table,
.observable = world
});
ecs_readonly_end(world);
test_int(ctx.invoked, 1);
test_assert(ctx.system == s);
test_assert(ctx.event == evt);
test_assert(ctx.event_id == id);
test_int(ctx.count, 1);
test_assert(ctx.e[0] == e);
ecs_fini(world);
}
void Event_emit_staged_from_world_observer(void) {
ecs_world_t *world = ecs_mini();
ecs_entity_t evt = ecs_new_id(world);
ecs_entity_t id = ecs_new_id(world);
ecs_entity_t e = ecs_new_w_id(world, id);
ecs_table_t *table = ecs_get_table(world, e);
Probe ctx = {0};
ecs_entity_t s = ecs_observer_init(world, &(ecs_observer_desc_t){
.filter.terms = {{ id }},
.events = {evt},
.callback = system_callback,
.ctx = &ctx
});
ecs_readonly_begin(world);
ecs_emit(world, &(ecs_event_desc_t){
.event = evt,
.ids = &(ecs_type_t){.count = 1, .array = (ecs_id_t[]){ id }},
.table = table,
.observable = world
});
ecs_readonly_end(world);
test_int(ctx.invoked, 1);
test_assert(ctx.system == s);
test_assert(ctx.event == evt);
test_assert(ctx.event_id == id);
test_int(ctx.count, 1);
test_assert(ctx.e[0] == e);
ecs_fini(world);
}
void Event_emit_staged_from_stage_observer(void) {
ecs_world_t *world = ecs_mini();
ecs_entity_t evt = ecs_new_id(world);
ecs_entity_t id = ecs_new_id(world);
ecs_entity_t e = ecs_new_w_id(world, id);
ecs_table_t *table = ecs_get_table(world, e);
Probe ctx = {0};
ecs_entity_t s = ecs_observer_init(world, &(ecs_observer_desc_t){
.filter.terms = {{ id }},
.events = {evt},
.callback = system_callback,
.ctx = &ctx
});
ecs_readonly_begin(world);
ecs_world_t *stage = ecs_get_stage(world, 0);
ecs_emit(stage, &(ecs_event_desc_t){
.event = evt,
.ids = &(ecs_type_t){.count = 1, .array = (ecs_id_t[]){ id }},
.table = table,
.observable = world
});
ecs_readonly_end(world);
test_int(ctx.invoked, 1);
test_assert(ctx.system == s);
test_assert(ctx.event == evt);
test_assert(ctx.event_id == id);
test_int(ctx.count, 1);
test_assert(ctx.e[0] == e);
ecs_fini(world);
}
void Event_emit_for_entity(void) {
ecs_world_t *world = ecs_mini();
ecs_entity_t evt = ecs_new_id(world);
ecs_entity_t id = ecs_new_id(world);
ecs_entity_t e = ecs_new_w_id(world, id);
Probe ctx = {0};
ecs_entity_t s = ecs_observer_init(world, &(ecs_observer_desc_t){
.filter.terms[0].id = id,
.events = {evt},
.callback = system_callback,
.ctx = &ctx
});
ecs_emit(world, &(ecs_event_desc_t){
.event = evt,
.ids = &(ecs_type_t){.count = 1, .array = (ecs_id_t[]){ id }},
.entity = e
});
test_int(ctx.invoked, 1);
test_assert(ctx.system == s);
test_assert(ctx.event == evt);
test_assert(ctx.event_id == id);
test_int(ctx.count, 1);
test_assert(ctx.e[0] == e);
ecs_fini(world);
}
static int ObserverA_invoked = false;
static void ObserverA(ecs_iter_t *it) {
ObserverA_invoked ++;
}
static int ObserverB_invoked = false;
static void ObserverB(ecs_iter_t *it) {
ObserverB_invoked ++;
}
void Event_emit_custom_for_any(void) {
ecs_world_t *world = ecs_mini();
ECS_TAG(world, Tag);
ecs_entity_t MyEvent = ecs_new_id(world);
ecs_entity_t e1 = ecs_new(world, Tag);
ecs_entity_t e2 = ecs_new(world, Tag);
ecs_observer(world, {
.filter.terms = {{ .id = EcsAny, .src.id = e1 }},
.events = {MyEvent},
.callback = ObserverA
});
ecs_observer(world, {
.filter.terms = {{ .id = EcsAny, .src.id = e2 }},
.events = {MyEvent},
.callback = ObserverB
});
ecs_emit(world, &(ecs_event_desc_t) {
.ids = &(ecs_type_t){ .count = 1, .array = (ecs_id_t[]){ EcsAny } },
.entity = e1,
.event = MyEvent
});
test_int(ObserverA_invoked, 1);
test_int(ObserverB_invoked, 0);
ecs_emit(world, &(ecs_event_desc_t) {
.ids = &(ecs_type_t){ .count = 1, .array = (ecs_id_t[]){ EcsAny } },
.entity = e2,
.event = MyEvent
});
test_int(ObserverA_invoked, 1);
test_int(ObserverB_invoked, 1);
ecs_fini(world);
}
void Event_emit_custom_implicit_any(void) {
ecs_world_t *world = ecs_mini();
ECS_TAG(world, Tag);
ecs_entity_t MyEvent = ecs_new_id(world);
ecs_entity_t e1 = ecs_new(world, Tag);
ecs_entity_t e2 = ecs_new(world, Tag);
ecs_observer(world, {
.filter.terms = {{ .id = EcsAny, .src.id = e1 }},
.events = {MyEvent},
.callback = ObserverA
});
ecs_observer(world, {
.filter.terms = {{ .id = EcsAny, .src.id = e2 }},
.events = {MyEvent},
.callback = ObserverB
});
ecs_emit(world, &(ecs_event_desc_t) {
.entity = e1,
.event = MyEvent
});
test_int(ObserverA_invoked, 1);
test_int(ObserverB_invoked, 0);
ecs_emit(world, &(ecs_event_desc_t) {
.entity = e2,
.event = MyEvent
});
test_int(ObserverA_invoked, 1);
test_int(ObserverB_invoked, 1);
ecs_fini(world);
}
void Event_emit_custom_empty_type(void) {
ecs_world_t *world = ecs_mini();
ECS_TAG(world, Tag);
ecs_entity_t MyEvent = ecs_new_id(world);
ecs_entity_t e1 = ecs_new(world, Tag);
ecs_entity_t e2 = ecs_new(world, Tag);
ecs_observer(world, {
.filter.terms = {{ .id = EcsAny, .src.id = e1 }},
.events = {MyEvent},
.callback = ObserverA
});
ecs_observer(world, {
.filter.terms = {{ .id = EcsAny, .src.id = e2 }},
.events = {MyEvent},
.callback = ObserverB
});
ecs_emit(world, &(ecs_event_desc_t) {
.ids = &(ecs_type_t){ .count = 0 },
.entity = e1,
.event = MyEvent
});
test_int(ObserverA_invoked, 1);
test_int(ObserverB_invoked, 0);
ecs_emit(world, &(ecs_event_desc_t) {
.ids = &(ecs_type_t){ .count = 0 },
.entity = e2,
.event = MyEvent
});
test_int(ObserverA_invoked, 1);
test_int(ObserverB_invoked, 1);
ecs_fini(world);
}

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,500 @@
#include <api.h>
void FilterStr_one_term(void) {
ecs_world_t *world = ecs_mini();
ECS_TAG(world, TagA);
ecs_filter_t f = ECS_FILTER_INIT;
test_assert(NULL != ecs_filter_init(world, &(ecs_filter_desc_t){
.storage = &f,
.terms = {{ TagA }}
}));
char *str = ecs_filter_str(world, &f);
test_str(str, "TagA");
ecs_os_free(str);
ecs_filter_fini(&f);
ecs_fini(world);
}
void FilterStr_one_term_w_inout(void) {
ecs_world_t *world = ecs_mini();
ECS_TAG(world, TagA);
ECS_TAG(world, TagB);
ecs_filter_t f = ECS_FILTER_INIT;
test_assert(NULL != ecs_filter_init(world, &(ecs_filter_desc_t){
.storage = &f,
.terms = {
{ TagA, .inout = EcsIn }
}
}));
char *str = ecs_filter_str(world, &f);
test_str(str, "[in] TagA");
ecs_os_free(str);
ecs_filter_fini(&f);
ecs_fini(world);
}
void FilterStr_two_terms(void) {
ecs_world_t *world = ecs_mini();
ECS_TAG(world, TagA);
ECS_TAG(world, TagB);
ecs_filter_t f = ECS_FILTER_INIT;
test_assert(NULL != ecs_filter_init(world, &(ecs_filter_desc_t){
.storage = &f,
.terms = {
{ TagA },
{ TagB }
}
}));
char *str = ecs_filter_str(world, &f);
test_str(str, "TagA, TagB");
ecs_os_free(str);
ecs_filter_fini(&f);
ecs_fini(world);
}
void FilterStr_two_terms_w_inout(void) {
ecs_world_t *world = ecs_mini();
ECS_TAG(world, TagA);
ECS_TAG(world, TagB);
ecs_filter_t f = ECS_FILTER_INIT;
test_assert(NULL != ecs_filter_init(world, &(ecs_filter_desc_t){
.storage = &f,
.terms = {
{ TagA },
{ TagB, .inout = EcsIn }
}
}));
char *str = ecs_filter_str(world, &f);
test_str(str, "TagA, [in] TagB");
ecs_os_free(str);
ecs_filter_fini(&f);
ecs_fini(world);
}
void FilterStr_three_terms_w_or(void) {
ecs_world_t *world = ecs_mini();
ECS_TAG(world, TagA);
ECS_TAG(world, TagB);
ECS_TAG(world, TagC);
ecs_filter_t f = ECS_FILTER_INIT;
test_assert(NULL != ecs_filter_init(world, &(ecs_filter_desc_t){
.storage = &f,
.terms = {
{ TagA },
{ TagB, .oper = EcsOr },
{ TagC }
}
}));
char *str = ecs_filter_str(world, &f);
test_str(str, "TagA, TagB || TagC");
ecs_os_free(str);
ecs_filter_fini(&f);
ecs_fini(world);
}
void FilterStr_three_terms_w_or_inout(void) {
ecs_world_t *world = ecs_mini();
ECS_TAG(world, TagA);
ECS_TAG(world, TagB);
ECS_TAG(world, TagC);
ecs_filter_t f = ECS_FILTER_INIT;
test_assert(NULL != ecs_filter_init(world, &(ecs_filter_desc_t){
.storage = &f,
.terms = {
{ TagA },
{ TagB, .oper = EcsOr, .inout = EcsIn },
{ TagC, .inout = EcsIn }
}
}));
char *str = ecs_filter_str(world, &f);
test_str(str, "TagA, [in] TagB || TagC");
ecs_os_free(str);
ecs_filter_fini(&f);
ecs_fini(world);
}
void FilterStr_four_terms_three_w_or_inout(void) {
ecs_world_t *world = ecs_mini();
ECS_TAG(world, TagA);
ECS_TAG(world, TagB);
ECS_TAG(world, TagC);
ECS_TAG(world, TagD);
ecs_filter_t f = ECS_FILTER_INIT;
test_assert(NULL != ecs_filter_init(world, &(ecs_filter_desc_t){
.storage = &f,
.terms = {
{ TagA },
{ TagB, .oper = EcsOr, .inout = EcsIn },
{ TagC, .inout = EcsIn },
{ TagD, .inout = EcsIn }
}
}));
char *str = ecs_filter_str(world, &f);
test_str(str, "TagA, [in] TagB || TagC, [in] TagD");
ecs_os_free(str);
ecs_filter_fini(&f);
ecs_fini(world);
}
void FilterStr_one_term_w_pair(void) {
ecs_world_t *world = ecs_mini();
ECS_TAG(world, Rel);
ECS_TAG(world, Tgt);
ecs_filter_t f = ECS_FILTER_INIT;
test_assert(NULL != ecs_filter_init(world, &(ecs_filter_desc_t){
.storage = &f,
.terms = {{ .id = ecs_pair(Rel, Tgt) }}
}));
char *str = ecs_filter_str(world, &f);
test_str(str, "(Rel,Tgt)");
ecs_os_free(str);
ecs_filter_fini(&f);
ecs_fini(world);
}
void FilterStr_one_term_w_pair_entity_src(void) {
ecs_world_t *world = ecs_mini();
ECS_TAG(world, Rel);
ECS_TAG(world, Src);
ECS_TAG(world, Tgt);
ecs_filter_t f = ECS_FILTER_INIT;
test_assert(NULL != ecs_filter_init(world, &(ecs_filter_desc_t){
.storage = &f,
.terms = {{ .id = ecs_pair(Rel, Tgt), .src.id = Src }}
}));
char *str = ecs_filter_str(world, &f);
test_str(str, "Rel(Src,Tgt)");
ecs_os_free(str);
ecs_filter_fini(&f);
ecs_fini(world);
}
void FilterStr_one_term_w_self(void) {
ecs_world_t *world = ecs_mini();
ECS_TAG(world, Foo);
ecs_filter_t f = ECS_FILTER_INIT;
test_assert(NULL != ecs_filter_init(world, &(ecs_filter_desc_t){
.storage = &f,
.terms = {{ .id = Foo, .src.flags = EcsSelf }}
}));
char *str = ecs_filter_str(world, &f);
test_str(str, "Foo(self)");
ecs_os_free(str);
ecs_filter_fini(&f);
ecs_fini(world);
}
void FilterStr_one_term_w_up(void) {
ecs_world_t *world = ecs_mini();
ECS_TAG(world, Foo);
ecs_filter_t f = ECS_FILTER_INIT;
test_assert(NULL != ecs_filter_init(world, &(ecs_filter_desc_t){
.storage = &f,
.terms = {{ .id = Foo, .src.flags = EcsUp }}
}));
char *str = ecs_filter_str(world, &f);
test_str(str, "Foo(up)");
ecs_os_free(str);
ecs_filter_fini(&f);
ecs_fini(world);
}
void FilterStr_one_term_w_0(void) {
ecs_world_t *world = ecs_mini();
ECS_TAG(world, Foo);
ecs_filter_t f = ECS_FILTER_INIT;
test_assert(NULL != ecs_filter_init(world, &(ecs_filter_desc_t){
.storage = &f,
.terms = {{ .id = Foo, .src.flags = EcsIsEntity }}
}));
char *str = ecs_filter_str(world, &f);
test_str(str, "Foo()");
ecs_os_free(str);
ecs_filter_fini(&f);
ecs_fini(world);
}
void FilterStr_one_term_w_singleton(void) {
ecs_world_t *world = ecs_mini();
ECS_TAG(world, Foo);
ecs_filter_t f = ECS_FILTER_INIT;
test_assert(NULL != ecs_filter_init(world, &(ecs_filter_desc_t){
.storage = &f,
.terms = {{ .id = Foo, .src.id = Foo }}
}));
char *str = ecs_filter_str(world, &f);
test_str(str, "Foo($)");
ecs_os_free(str);
ecs_filter_fini(&f);
ecs_fini(world);
}
void FilterStr_one_term_w_final_pair(void) {
ecs_world_t *world = ecs_mini();
ECS_ENTITY(world, Foo, Final);
ecs_filter_t f = ECS_FILTER_INIT;
test_assert(NULL != ecs_filter_init(world, &(ecs_filter_desc_t){
.storage = &f,
.terms = {{ .first.id = Foo }}
}));
char *str = ecs_filter_str(world, &f);
test_str(str, "Foo");
ecs_os_free(str);
ecs_filter_fini(&f);
ecs_fini(world);
}
void FilterStr_one_term_w_final_dont_inherit_pair(void) {
ecs_world_t *world = ecs_mini();
ECS_ENTITY(world, Foo, Final, DontInherit);
ecs_filter_t f = ECS_FILTER_INIT;
test_assert(NULL != ecs_filter_init(world, &(ecs_filter_desc_t){
.storage = &f,
.terms = {{ .first.id = Foo }}
}));
char *str = ecs_filter_str(world, &f);
test_str(str, "Foo");
ecs_os_free(str);
ecs_filter_fini(&f);
ecs_fini(world);
}
void FilterStr_one_term_w_src_var(void) {
ecs_world_t *world = ecs_mini();
ECS_TAG(world, Tag);
ecs_filter_t f = ECS_FILTER_INIT;
test_assert(NULL != ecs_filter_init(world, &(ecs_filter_desc_t){
.storage = &f,
.terms = {{ Tag, .src.flags = EcsIsVariable, .src.name = "Var" }}
}));
char *str = ecs_filter_str(world, &f);
test_str(str, "Tag($Var)");
ecs_os_free(str);
ecs_filter_fini(&f);
ecs_fini(world);
}
void FilterStr_one_term_w_first_var(void) {
ecs_world_t *world = ecs_mini();
ecs_filter_t f = ECS_FILTER_INIT;
test_assert(NULL != ecs_filter_init(world, &(ecs_filter_desc_t){
.storage = &f,
.terms = {{ .first.flags = EcsIsVariable, .first.name = "Var" }}
}));
char *str = ecs_filter_str(world, &f);
test_str(str, "[none] $Var");
ecs_os_free(str);
ecs_filter_fini(&f);
ecs_fini(world);
}
void FilterStr_one_term_w_second_var(void) {
ecs_world_t *world = ecs_mini();
ECS_TAG(world, Rel);
ecs_filter_t f = ECS_FILTER_INIT;
test_assert(NULL != ecs_filter_init(world, &(ecs_filter_desc_t){
.storage = &f,
.terms = {{ .first.id = Rel, .second.flags = EcsIsVariable, .second.name = "Var" }}
}));
char *str = ecs_filter_str(world, &f);
test_str(str, "(Rel,$Var)");
ecs_os_free(str);
ecs_filter_fini(&f);
ecs_fini(world);
}
void FilterStr_one_term_w_first_var_entity_src(void) {
ecs_world_t *world = ecs_mini();
ECS_TAG(world, Src);
ecs_filter_t f = ECS_FILTER_INIT;
test_assert(NULL != ecs_filter_init(world, &(ecs_filter_desc_t){
.storage = &f,
.terms = {{ .first.flags = EcsIsVariable, .first.name = "Var", .src.id = Src }}
}));
char *str = ecs_filter_str(world, &f);
test_str(str, "[none] $Var(Src)");
ecs_os_free(str);
ecs_filter_fini(&f);
ecs_fini(world);
}
void FilterStr_one_term_w_pair_w_0_entity(void) {
ecs_world_t *world = ecs_mini();
ECS_TAG(world, Rel);
ECS_TAG(world, Tgt);
ecs_filter_t f = ECS_FILTER_INIT;
test_assert(NULL != ecs_filter_init(world, &(ecs_filter_desc_t){
.storage = &f,
.terms = {
{ .first.id = Rel, .second.id = Tgt, .src = {
.id = 0, .flags = EcsIsEntity
} }
}
}));
char *str = ecs_filter_str(world, &f);
test_str(str, "Rel(0,Tgt)");
ecs_os_free(str);
ecs_filter_fini(&f);
ecs_fini(world);
}
void FilterStr_not_term(void) {
ecs_world_t *world = ecs_mini();
ECS_TAG(world, TagA);
ecs_filter_t f = ECS_FILTER_INIT;
test_assert(NULL != ecs_filter_init(world, &(ecs_filter_desc_t){
.storage = &f,
.terms = {{ TagA, .oper = EcsNot }}
}));
char *str = ecs_filter_str(world, &f);
test_str(str, "!TagA");
ecs_os_free(str);
ecs_filter_fini(&f);
ecs_fini(world);
}
void FilterStr_wildcard_term(void) {
ecs_world_t *world = ecs_mini();
ECS_TAG(world, TagA);
ecs_filter_t f = ECS_FILTER_INIT;
test_assert(NULL != ecs_filter_init(world, &(ecs_filter_desc_t){
.storage = &f,
.terms = {{ EcsWildcard }}
}));
char *str = ecs_filter_str(world, &f);
test_str(str, "[none] *");
ecs_os_free(str);
ecs_filter_fini(&f);
ecs_fini(world);
}
void FilterStr_scopes(void) {
ecs_world_t *world = ecs_mini();
ECS_TAG(world, TagA);
ECS_TAG(world, TagB);
ECS_TAG(world, TagC);
ecs_filter_t f = ECS_FILTER_INIT;
test_assert(NULL != ecs_filter_init(world, &(ecs_filter_desc_t){
.storage = &f,
.expr = "TagA, {TagB, {TagC}}"
}));
char *str = ecs_filter_str(world, &f);
test_str(str, "TagA, {TagB, {TagC}}");
ecs_os_free(str);
ecs_filter_fini(&f);
ecs_fini(world);
}

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,282 @@
#include <api.h>
void Get_component_setup(void) {
ecs_log_set_level(-3);
}
void Get_component_get_empty(void) {
ecs_world_t *world = ecs_mini();
ecs_entity_t e = ecs_new(world, 0);
test_assert(e != 0);
test_assert(ecs_get_type(world, e) == NULL);
ecs_fini(world);
}
void Get_component_get_1_from_1(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_get_type(world, e)->array[0] == ecs_id(Position));
ecs_fini(world);
}
void Get_component_get_1_from_2(void) {
ecs_world_t *world = ecs_mini();
ECS_COMPONENT(world, Position);
ECS_COMPONENT(world, Velocity);
ECS_ENTITY(world, e, Position, Velocity);
test_assert(e != 0);
test_assert(ecs_get_type(world, e)->array[0] == ecs_id(Position));
ecs_fini(world);
}
void Get_component_get_2_from_2(void) {
ecs_world_t *world = ecs_mini();
ECS_COMPONENT(world, Position);
ECS_COMPONENT(world, Velocity);
ECS_ENTITY(world, e, Position, Velocity);
test_assert(e != 0);
test_assert(ecs_get_type(world, e)->array[1] == ecs_id(Velocity));
ecs_fini(world);
}
void Get_component_get_2_from_3(void) {
ecs_world_t *world = ecs_mini();
ECS_COMPONENT(world, Position);
ECS_COMPONENT(world, Velocity);
ECS_COMPONENT(world, Mass);
ECS_ENTITY(world, e, Position, Velocity, Mass);
test_assert(e != 0);
test_assert(ecs_get_type(world, e)->array[1] == ecs_id(Velocity));
ecs_fini(world);
}
static
void Test_main_stage(ecs_iter_t *it) {
ecs_id_t ecs_id(Position) = ecs_field_id(it, 1);
for (int i = 0; i < it->count; i ++) {
ecs_entity_t e = it->entities[i];
test_assert(ecs_get_type(it->world, e)->array[0] == ecs_id(Position));
}
}
void Get_component_get_1_from_2_in_progress_from_main_stage(void) {
ecs_world_t *world = ecs_init();
ECS_COMPONENT(world, Position);
ecs_entity_t e = ecs_new(world, Position);
test_assert(e != 0);
ECS_SYSTEM(world, Test_main_stage, EcsOnUpdate, Position);
ecs_progress(world, 1);
ecs_fini(world);
}
static
void Add_in_progress(ecs_iter_t *it) {
ecs_id_t ecs_id(Velocity) = 0;
if (it->field_count >= 2) {
ecs_id(Velocity) = ecs_field_id(it, 2);
}
for (int i = 0; i < it->count; i ++) {
ecs_entity_t e = it->entities[i];
ecs_add(it->world, e, Velocity);
test_assert(!ecs_has(it->world, e, Velocity));
}
}
void Get_component_get_1_from_2_add_in_progress(void) {
ecs_world_t *world = ecs_init();
ECS_COMPONENT(world, Position);
ECS_COMPONENT(world, Velocity);
ecs_entity_t e = ecs_new(world, Position);
test_assert(e != 0);
ECS_SYSTEM(world, Add_in_progress, EcsOnUpdate, Position, Velocity());
ecs_progress(world, 1);
test_assert( ecs_has(world, e, Velocity));
test_assert(ecs_get_type(world, e)->array[1] == ecs_id(Velocity));
ecs_fini(world);
}
static
void Add_in_progress_test_main(ecs_iter_t *it) {
ecs_id_t ecs_id(Position) = ecs_field_id(it, 1);
ecs_id_t ecs_id(Velocity) = ecs_field_id(it, 2);
for (int i = 0; i < it->count; i ++) {
ecs_entity_t e = it->entities[i];
test_assert(ecs_get_type(it->world, e)->array[0] == ecs_id(Position));
ecs_add(it->world, e, Velocity);
}
}
void Get_component_get_both_from_2_add_in_progress(void) {
ecs_world_t *world = ecs_init();
ECS_COMPONENT(world, Position);
ECS_COMPONENT(world, Velocity);
ecs_entity_t e = ecs_new(world, Position);
test_assert(e != 0);
ECS_SYSTEM(world, Add_in_progress_test_main, EcsOnUpdate, Position, Velocity());
ecs_progress(world, 1);
test_assert( ecs_has(world, e, Velocity));
test_assert(ecs_get_type(world, e)->array[0] == ecs_id(Position));
test_assert(ecs_get_type(world, e)->array[1] == ecs_id(Velocity));
ecs_fini(world);
}
static
void Add_remove_in_progress_test_main(ecs_iter_t *it) {
ecs_id_t ecs_id(Position) = ecs_field_id(it, 1);
ecs_id_t ecs_id(Velocity) = ecs_field_id(it, 2);
for (int i = 0; i < it->count; i ++) {
ecs_entity_t e = it->entities[i];
test_assert(ecs_get_type(it->world, e)->array[0] == ecs_id(Position));
ecs_add(it->world, e, Velocity);
ecs_remove(it->world, e, Position);
}
}
void Get_component_get_both_from_2_add_remove_in_progress(void) {
ecs_world_t *world = ecs_init();
ECS_COMPONENT(world, Position);
ECS_COMPONENT(world, Velocity);
ecs_entity_t e = ecs_new(world, Position);
test_assert(e != 0);
ECS_SYSTEM(world, Add_remove_in_progress_test_main, EcsOnUpdate, Position, Velocity());
ecs_progress(world, 1);
test_assert( !ecs_has(world, e, Position));
test_assert( ecs_has(world, e, Velocity));
test_assert(ecs_get_type(world, e)->array[0] == ecs_id(Velocity));
test_assert(ecs_get_type(world, e)->count == 1);
ecs_fini(world);
}
void Get_component_get_childof_component(void) {
install_test_abort();
ecs_world_t *world = ecs_mini();
ECS_COMPONENT(world, Position);
const EcsComponent *ptr = ecs_get(world, ecs_id(Position), EcsComponent);
test_assert(ptr != NULL);
test_expect_abort();
ecs_get(world, ecs_pair(EcsChildOf, ecs_id(Position)), EcsComponent);
}
void Get_component_get_mut_equal_get(void) {
ecs_world_t *world = ecs_mini();
ECS_COMPONENT(world, Position);
ECS_COMPONENT(world, Velocity);
ECS_ENTITY(world, e, Position);
test_assert(e != 0);
test_assert(ecs_get_mut(world, e, Position) == ecs_get(world, e,
Position));
ecs_fini(world);
}
void Get_component_get_tag(void) {
install_test_abort();
ecs_world_t *world = ecs_mini();
ECS_TAG(world, Tag);
ecs_entity_t e = ecs_new(world, Tag);
test_assert(e != 0);
test_expect_abort();
ecs_get_id(world, e, Tag);
ecs_fini(world);
}
void Get_component_get_pair_tag(void) {
install_test_abort();
ecs_world_t *world = ecs_mini();
ecs_entity_t parent = ecs_new_id(world);
ecs_entity_t e = ecs_new_w_pair(world, EcsChildOf, parent);
test_assert(e != 0);
test_expect_abort();
ecs_get_id(world, e, ecs_childof(parent));
ecs_fini(world);
}
void Get_component_get_wildcard(void) {
ecs_world_t *world = ecs_mini();
ECS_COMPONENT(world, Position);
ECS_TAG(world, Tgt);
ecs_entity_t e = ecs_set_pair(world, 0, Position, Tgt, {10, 20});
test_assert(e != 0);
test_assert(ecs_has_pair(world, e, ecs_id(Position), Tgt));
{
const Position *p = ecs_get_pair(world, e, Position, Tgt);
test_assert(p != NULL);
test_int(p->x, 10);
test_int(p->y, 20);
}
{
const Position *p = ecs_get_pair(world, e, Position, EcsWildcard);
test_assert(p != NULL);
test_int(p->x, 10);
test_int(p->y, 20);
}
ecs_fini(world);
}

View File

@@ -0,0 +1,153 @@
#include <api.h>
static ECS_DECLARE(MyTag);
static ECS_DECLARE(MyEntity);
static ECS_COMPONENT_DECLARE(Position);
static ECS_COMPONENT_DECLARE(Velocity);
static
ecs_entity_t create_entity(ecs_world_t *world) {
return ecs_new(world, Position);
}
static
ecs_entity_t create_entity_w_entity(ecs_world_t *world) {
return ecs_new_w_id(world, ecs_id(Position));
}
static
ecs_entity_t create_tag_entity(ecs_world_t *world) {
return ecs_new(world, MyTag);
}
static
ecs_entity_t create_tag_entity_w_entity(ecs_world_t *world) {
return ecs_new_w_id(world, MyTag);
}
static ecs_entity_t return_entity(void) {
return MyEntity;
}
void GlobalComponentIds_declare(void) {
ecs_world_t *world = ecs_mini();
ECS_COMPONENT_DEFINE(world, Position);
ecs_entity_t e = create_entity(world);
test_assert(e != 0);
test_assert(ecs_has(world, e, Position));
ecs_fini(world);
}
void GlobalComponentIds_declare_w_entity(void) {
ecs_world_t *world = ecs_mini();
ECS_COMPONENT_DEFINE(world, Position);
ecs_entity_t e = create_entity_w_entity(world);
test_assert(e != 0);
test_assert(ecs_has(world, e, Position));
ecs_fini(world);
}
void GlobalComponentIds_declare_2_world(void) {
ecs_world_t *world_1 = ecs_mini();
ECS_COMPONENT_DEFINE(world_1, Position);
ECS_COMPONENT_DEFINE(world_1, Velocity);
ecs_entity_t e_pos = ecs_id(Position);
ecs_entity_t e_vel = ecs_id(Velocity);
ecs_world_t *world_2 = ecs_mini();
/* Declare in reverse order, ensure that ids are still the same */
ECS_COMPONENT_DEFINE(world_2, Velocity);
ECS_COMPONENT_DEFINE(world_2, Position);
test_assert(e_pos == ecs_id(Position));
test_assert(e_vel == ecs_id(Velocity));
ecs_fini(world_1);
ecs_fini(world_2);
}
void GlobalComponentIds_declare_tag(void) {
ecs_world_t *world = ecs_mini();
ECS_TAG_DEFINE(world, MyTag);
ecs_entity_t e = create_tag_entity(world);
test_assert(e != 0);
test_assert(ecs_has(world, e, MyTag));
ecs_fini(world);
}
void GlobalComponentIds_declare_tag_w_entity(void) {
ecs_world_t *world = ecs_mini();
ECS_TAG_DEFINE(world, MyTag);
ecs_entity_t e = create_tag_entity_w_entity(world);
test_assert(e != 0);
test_assert(ecs_has(world, e, MyTag));
ecs_fini(world);
}
void GlobalComponentIds_declare_entity(void) {
ecs_world_t *world = ecs_mini();
ECS_COMPONENT_DEFINE(world, Position);
ECS_ENTITY_DEFINE(world, MyEntity, Position);
ecs_entity_t e = return_entity();
test_assert(e != 0);
test_assert(e == MyEntity);
test_assert(ecs_has(world, e, Position));
ecs_fini(world);
}
void GlobalComponentIds_reuse_300_component_ids(void) {
ecs_world_t *world = ecs_mini();
ecs_entity_t *ids = ecs_os_malloc_n(ecs_entity_t, 300);
for (int i = 0; i < 300; i ++) {
ids[i] = ecs_component_init(world, &(ecs_component_desc_t){
.type.size = 1,
.type.alignment = 1
});
}
const ecs_world_info_t *info = ecs_get_world_info(world);
ecs_entity_t info_last_component_id = info->last_component_id;
ecs_entity_t info_last_id = ecs_get_max_id(world);
ecs_entity_t next_id = ecs_new_id(world);
ecs_fini(world);
world = ecs_mini();
for (int i = 0; i < 300; i ++) {
ids[i] = ecs_component_init(world, &(ecs_component_desc_t){
.entity = ids[i],
.type.size = 1,
.type.alignment = 1
});
}
info = ecs_get_world_info(world);
test_int(info->last_component_id, info_last_component_id);
test_int(ecs_get_max_id(world), info_last_id);
test_int(next_id, ecs_new_id(world));
ecs_os_free(ids);
ecs_fini(world);
}

View File

@@ -0,0 +1,314 @@
#include <api.h>
void Has_zero(void) {
install_test_abort();
ecs_world_t *world = ecs_mini();
ecs_entity_t e = ecs_new(world, 0);
test_assert(e != 0);
test_expect_abort();
ecs_has(world, e, 0);
}
void Has_1_of_0(void) {
ecs_world_t *world = ecs_mini();
ECS_COMPONENT(world, Position);
ecs_entity_t e = ecs_new(world, 0);
test_assert(e != 0);
test_assert(!ecs_has(world, e, Position));
ecs_fini(world);
}
void Has_1_of_1(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_has(world, e, Position));
ecs_fini(world);
}
void Has_1_of_2(void) {
ecs_world_t *world = ecs_mini();
ECS_COMPONENT(world, Position);
ECS_COMPONENT(world, Velocity);
ECS_ENTITY(world, e, Position, Velocity);
test_assert(e != 0);
test_assert(ecs_has(world, e, Position));
test_assert(ecs_has(world, e, Velocity));
ecs_fini(world);
}
void Has_1_of_empty(void) {
ecs_world_t *world = ecs_mini();
ECS_COMPONENT(world, Position);
ecs_entity_t e = ecs_new(world, 0);
test_assert(e != 0);
test_assert(!ecs_has(world, e, Position));
ecs_fini(world);
}
void TestHas(ecs_iter_t *it) {
ecs_id_t ecs_id(Position) = ecs_field_id(it, 1);
int i;
for (i = 0; i < it->count; i ++) {
test_assert( ecs_has(it->world, it->entities[i], Position));
}
}
void Has_has_in_progress(void) {
ecs_world_t *world = ecs_init();
ECS_COMPONENT(world, Position);
ECS_SYSTEM(world, TestHas, EcsOnUpdate, Position);
ecs_entity_t e = ecs_new(world, Position);
test_assert(e != 0);
test_assert( ecs_has(world, e, Position));
ecs_progress(world, 1);
ecs_fini(world);
}
void Has_has_of_zero(void) {
install_test_abort();
ecs_world_t *world = ecs_mini();
test_expect_abort();
ecs_has(world, 0, 0);
}
void Has_owns(void) {
ecs_world_t *world = ecs_mini();
ECS_COMPONENT(world, Position);
ECS_COMPONENT(world, Velocity);
ecs_entity_t e = ecs_new(world, Position);
test_assert(e != 0);
test_assert( ecs_has(world, e, Position));
test_assert( ecs_owns(world, e, Position));
ecs_entity_t base = ecs_new(world, Velocity);
test_assert( ecs_has(world, base, Velocity));
test_assert( ecs_owns(world, base, Velocity));
ecs_add_pair(world, e, EcsIsA, base);
test_assert( ecs_has(world, e, Velocity));
test_assert( !ecs_owns(world, e, Velocity));
ecs_fini(world);
}
void Has_owns_wildcard(void) {
ecs_world_t *world = ecs_mini();
ECS_TAG(world, Tag_1);
ECS_TAG(world, Tag_2);
ecs_entity_t e1 = ecs_new_id(world);
test_assert(e1 != 0);
ecs_entity_t e2 = ecs_new_id(world);
test_assert(e2 != 0);
ecs_add_id(world, e1, Tag_1);
test_bool(ecs_owns_id(world, e1, Tag_1), true);
test_bool(ecs_owns_id(world, e1, Tag_2), false);
test_bool(ecs_owns_id(world, e1, EcsWildcard), true);
test_bool(ecs_owns_id(world, e2, Tag_1), false);
test_bool(ecs_owns_id(world, e2, Tag_2), false);
test_bool(ecs_owns_id(world, e2, EcsWildcard), false);
ecs_fini(world);
}
void Has_owns_wildcard_pair(void) {
ecs_world_t *world = ecs_mini();
ECS_TAG(world, Rel);
ECS_TAG(world, Obj_1);
ECS_TAG(world, Obj_2);
ecs_entity_t e = ecs_new_id(world);
test_assert(e != 0);
ecs_add_pair(world, e, Rel, Obj_1);
test_bool(ecs_owns_pair(world, e, Rel, Obj_1), true);
test_bool(ecs_owns_pair(world, e, Rel, Obj_2), false);
test_bool(ecs_owns_pair(world, e, Rel, EcsWildcard), true);
test_bool(ecs_owns_pair(world, e, EcsWildcard, Obj_1), true);
test_bool(ecs_owns_pair(world, e, EcsWildcard, Obj_2), false);
test_bool(ecs_owns_pair(world, e, EcsWildcard, EcsWildcard), true);
ecs_fini(world);
}
void Has_has_entity(void) {
ecs_world_t *world = ecs_mini();
ecs_entity_t e = ecs_new(world, 0);
test_assert(e != 0);
ecs_entity_t base = ecs_new(world, 0);
test_assert(base != 0);
ecs_add_pair(world, e, EcsIsA, base);
test_assert( !ecs_has_id(world, e, base));
test_assert( ecs_has_pair(world, e, EcsIsA, base));
ecs_fini(world);
}
void Has_has_entity_0(void) {
install_test_abort();
ecs_world_t *world = ecs_mini();
ecs_entity_t base = ecs_new(world, 0);
test_assert(base != 0);
test_expect_abort();
ecs_has_id(world, 0, base);
}
void Has_has_entity_0_component(void) {
install_test_abort();
ecs_world_t *world = ecs_mini();
ecs_entity_t e = ecs_new(world, 0);
test_assert(e != 0);
test_expect_abort();
ecs_has_id(world, e, 0);
}
void Has_has_entity_owned(void) {
ecs_world_t *world = ecs_mini();
ecs_entity_t e = ecs_new(world, 0);
test_assert(e != 0);
ecs_entity_t f = ecs_new(world, 0);
test_assert(f != 0);
ecs_entity_t g = ecs_new(world, 0);
test_assert(g != 0);
ecs_entity_t base = ecs_new(world, 0);
test_assert(base != 0);
ecs_add_id(world, e, f);
ecs_add_id(world, base, g);
ecs_add_pair(world, e, EcsIsA, base);
test_assert( ecs_has_id(world, e, f));
test_assert( ecs_has_id(world, e, g));
test_assert( !ecs_has_id(world, e, base));
test_assert( ecs_has_pair(world, e, EcsIsA, base));
test_assert( ecs_owns_id(world, e, f));
test_assert( !ecs_owns_id(world, e, g));
test_assert( !ecs_owns_id(world, e, base));
test_assert( ecs_owns_pair(world, e, EcsIsA, base) == true);
ecs_fini(world);
}
void Has_has_entity_owned_0(void) {
install_test_abort();
ecs_world_t *world = ecs_mini();
ecs_entity_t e = ecs_new(world, 0);
test_assert(e != 0);
test_expect_abort();
bool dummy = ecs_owns_id(world, 0, e);
test_assert(!dummy); // should not reach this code
}
void Has_has_entity_owned_0_component(void) {
ecs_world_t *world = ecs_mini();
ecs_entity_t e = ecs_new(world, 0);
test_assert(e != 0);
test_assert( ecs_owns_id(world, e, 0) == false);
ecs_fini(world);
}
void Has_has_wildcard(void) {
ecs_world_t *world = ecs_mini();
ECS_TAG(world, Tag_1);
ECS_TAG(world, Tag_2);
ecs_entity_t e1 = ecs_new_id(world);
test_assert(e1 != 0);
ecs_entity_t e2 = ecs_new_id(world);
test_assert(e2 != 0);
ecs_add_id(world, e1, Tag_1);
test_bool(ecs_has_id(world, e1, Tag_1), true);
test_bool(ecs_has_id(world, e1, Tag_2), false);
test_bool(ecs_has_id(world, e1, EcsWildcard), true);
test_bool(ecs_has_id(world, e2, Tag_1), false);
test_bool(ecs_has_id(world, e2, Tag_2), false);
test_bool(ecs_has_id(world, e2, EcsWildcard), false);
ecs_fini(world);
}
void Has_has_wildcard_pair(void) {
ecs_world_t *world = ecs_mini();
ECS_TAG(world, Rel);
ECS_TAG(world, Obj_1);
ECS_TAG(world, Obj_2);
ecs_entity_t e = ecs_new_id(world);
test_assert(e != 0);
ecs_add_pair(world, e, Rel, Obj_1);
test_bool(ecs_has_pair(world, e, Rel, Obj_1), true);
test_bool(ecs_has_pair(world, e, Rel, Obj_2), false);
test_bool(ecs_has_pair(world, e, Rel, EcsWildcard), true);
test_bool(ecs_has_pair(world, e, EcsWildcard, Obj_1), true);
test_bool(ecs_has_pair(world, e, EcsWildcard, Obj_2), false);
test_bool(ecs_has_pair(world, e, EcsWildcard, EcsWildcard), true);
ecs_fini(world);
}

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,213 @@
#include <api.h>
void Id_0_is_wildcard(void) {
test_assert( !ecs_id_is_wildcard(0) );
}
void Id_wildcard_is_wildcard(void) {
test_assert( ecs_id_is_wildcard(EcsWildcard) );
}
void Id_any_is_wildcard(void) {
test_assert( ecs_id_is_wildcard(EcsAny) );
}
void Id_entity_is_wildcard(void) {
ecs_world_t *world = ecs_mini();
ecs_entity_t e = ecs_new_id(world);
test_assert( !ecs_id_is_wildcard(e) );
ecs_fini(world);
}
void Id_pair_is_wildcard(void) {
ecs_world_t *world = ecs_mini();
ecs_entity_t r = ecs_new_id(world);
ecs_entity_t o = ecs_new_id(world);
test_assert( !ecs_id_is_wildcard(ecs_pair(r, o)) );
ecs_fini(world);
}
void Id_pair_w_rel_wildcard_is_wildcard(void) {
ecs_world_t *world = ecs_mini();
ecs_entity_t o = ecs_new_id(world);
test_assert( ecs_id_is_wildcard(ecs_pair(EcsWildcard, o)) );
ecs_fini(world);
}
void Id_pair_w_obj_wildcard_is_wildcard(void) {
ecs_world_t *world = ecs_mini();
ecs_entity_t r = ecs_new_id(world);
test_assert( ecs_id_is_wildcard(ecs_pair(r, EcsWildcard)) );
ecs_fini(world);
}
void Id_pair_w_wildcard_wildcard_is_wildcard(void) {
test_assert( ecs_id_is_wildcard(ecs_pair(EcsWildcard, EcsWildcard)) );
}
void Id_pair_w_rel_any_is_wildcard(void) {
ecs_world_t *world = ecs_mini();
ecs_entity_t o = ecs_new_id(world);
test_assert( ecs_id_is_wildcard(ecs_pair(EcsAny, o)) );
ecs_fini(world);
}
void Id_pair_w_obj_any_is_wildcard(void) {
ecs_world_t *world = ecs_mini();
ecs_entity_t r = ecs_new_id(world);
test_assert( ecs_id_is_wildcard(ecs_pair(r, EcsAny)) );
ecs_fini(world);
}
void Id_pair_w_any_any_is_wildcard(void) {
test_assert( ecs_id_is_wildcard(ecs_pair(EcsAny, EcsAny)) );
}
void Id_pair_w_override_is_wildcard(void) {
ecs_world_t *world = ecs_mini();
ecs_entity_t r = ecs_new_id(world);
test_assert( !ecs_id_is_wildcard(ECS_OVERRIDE | ecs_pair(r, EcsWildcard)));
ecs_fini(world);
}
void Id_pair_w_toggle_is_wildcard(void) {
ecs_world_t *world = ecs_mini();
ecs_entity_t r = ecs_new_id(world);
test_assert( !ecs_id_is_wildcard(ECS_TOGGLE | ecs_pair(r, EcsWildcard)));
ecs_fini(world);
}
void Id_tag_id_is_tag(void) {
ecs_world_t *world = ecs_mini();
ecs_entity_t t = ecs_new_id(world);
test_assert( ecs_id_is_tag(world, t));
ecs_fini(world);
}
void Id_component_id_is_tag(void) {
ecs_world_t *world = ecs_mini();
ECS_COMPONENT(world, Position);
test_assert( !ecs_id_is_tag(world, ecs_id(Position)));
ecs_fini(world);
}
void Id_pair_id_is_tag(void) {
ecs_world_t *world = ecs_mini();
ecs_entity_t r = ecs_new_id(world);
ecs_entity_t o = ecs_new_id(world);
test_assert( ecs_id_is_tag(world, ecs_pair(r, o)));
ecs_fini(world);
}
void Id_pair_id_w_rel_component_is_tag(void) {
ecs_world_t *world = ecs_mini();
ECS_COMPONENT(world, Position);
ecs_entity_t o = ecs_new_id(world);
test_assert( !ecs_id_is_tag(world, ecs_pair(ecs_id(Position), o)));
ecs_fini(world);
}
void Id_pair_id_w_obj_component_is_tag(void) {
ecs_world_t *world = ecs_mini();
ECS_COMPONENT(world, Position);
ecs_entity_t r = ecs_new_id(world);
test_assert( !ecs_id_is_tag(world, ecs_pair(r, ecs_id(Position))));
ecs_fini(world);
}
void Id_pair_id_w_rel_component_obj_wildcard_is_tag(void) {
ecs_world_t *world = ecs_mini();
ECS_COMPONENT(world, Position);
test_assert( !ecs_id_is_tag(world, ecs_pair(ecs_id(Position), EcsWildcard)));
ecs_fini(world);
}
void Id_pair_id_w_obj_wildcard_is_tag(void) {
ecs_world_t *world = ecs_mini();
ecs_entity_t r = ecs_new_id(world);
test_assert( !ecs_id_is_tag(world, ecs_pair(r, EcsWildcard)));
ecs_fini(world);
}
void Id_pair_id_w_tag_property_w_obj_component_is_tag(void) {
ecs_world_t *world = ecs_mini();
ECS_COMPONENT(world, Position);
ecs_entity_t r = ecs_new_w_id(world, EcsTag);
test_assert( ecs_id_is_tag(world, ecs_pair(r, ecs_id(Position))));
ecs_fini(world);
}
void Id_pair_id_w_tag_property_w_obj_wildcard_is_tag(void) {
ecs_world_t *world = ecs_mini();
ECS_COMPONENT(world, Position);
ecs_entity_t r = ecs_new_w_id(world, EcsTag);
test_assert( ecs_id_is_tag(world, ecs_pair(r, EcsWildcard)));
ecs_fini(world);
}
void Id_id_w_override_is_tag(void) {
ecs_world_t *world = ecs_mini();
ECS_COMPONENT(world, Position);
test_assert( ecs_id_is_tag(world, ECS_OVERRIDE | ecs_id(Position)));
ecs_fini(world);
}
void Id_id_w_toggle_is_tag(void) {
ecs_world_t *world = ecs_mini();
ECS_COMPONENT(world, Position);
test_assert( ecs_id_is_tag(world, ECS_TOGGLE | ecs_id(Position)));
ecs_fini(world);
}
void Id_pair_id_override_is_tag(void) {
ecs_world_t *world = ecs_mini();
ECS_COMPONENT(world, Position);
ecs_entity_t o = ecs_new_id(world);
test_assert( ecs_id_is_tag(world, ECS_OVERRIDE | ecs_pair(ecs_id(Position), o)));
ecs_fini(world);
}
void Id_pair_id_toggle_is_tag(void) {
ecs_world_t *world = ecs_mini();
ECS_COMPONENT(world, Position);
ecs_entity_t o = ecs_new_id(world);
test_assert( ecs_id_is_tag(world, ECS_TOGGLE | ecs_pair(ecs_id(Position), o)));
ecs_fini(world);
}
void Id_make_pair(void) {
ecs_world_t *world = ecs_mini();
ecs_entity_t r = ecs_new_id(world);
ecs_entity_t t = ecs_new_id(world);
ecs_id_t id = ecs_make_pair(r, t);
test_assert( ecs_pair_first(world, id) == r);
test_assert( ecs_pair_second(world, id) == t);
ecs_fini(world);
}
void Id_make_pair_of_pair(void) {
install_test_abort();
ecs_world_t *world = ecs_mini();
ecs_entity_t r = ecs_new_id(world);
ecs_entity_t t = ecs_new_id(world);
ecs_id_t id = ecs_make_pair(r, t);
test_expect_abort();
ecs_make_pair(id, t);
}
void Id_make_pair_of_pair_tgt(void) {
install_test_abort();
ecs_world_t *world = ecs_mini();
ecs_entity_t r = ecs_new_id(world);
ecs_entity_t t = ecs_new_id(world);
ecs_id_t id = ecs_make_pair(r, t);
test_expect_abort();
ecs_make_pair(r, id);
}

View File

@@ -0,0 +1,517 @@
#include <api.h>
void Internals_setup(void) {
ecs_log_set_level(-3);
}
static
void Iter(ecs_iter_t *it) {
Position *p = ecs_field(it, Position, 1);
Velocity *v = ecs_field(it, Velocity, 2);
Mass *m = ecs_field(it, Mass, 3);
probe_iter(it);
int i;
for (i = 0; i < it->count; i ++) {
p[i].x = 10;
p[i].y = 20;
if (v) {
v[i].x = 30;
v[i].y = 40;
}
if (m) {
m[i] = 50;
}
}
}
void Internals_deactivate_table(void) {
ecs_world_t *world = ecs_init();
ECS_COMPONENT(world, Position);
ECS_ENTITY(world, e1, Position);
ECS_ENTITY(world, e2, Position);
ECS_SYSTEM(world, Iter, EcsOnUpdate, Position);
/* System is now matched with archetype of entities. Delete entities to
* deactivate table for system */
ecs_delete(world, e1);
ecs_delete(world, e2);
test_assert(true);
ecs_fini(world);
}
void Internals_activate_table(void) {
ecs_world_t *world = ecs_init();
ECS_COMPONENT(world, Position);
ECS_SYSTEM(world, Iter, EcsOnUpdate, Position);
/* Add entities after system definition to trigger table activation */
ECS_ENTITY(world, e1, Position);
ECS_ENTITY(world, e2, Position);
test_assert(true);
ecs_fini(world);
}
void Internals_activate_deactivate_table(void) {
ecs_world_t *world = ecs_init();
ECS_COMPONENT(world, Position);
ECS_SYSTEM(world, Iter, EcsOnUpdate, Position);
/* Add entities after system definition to trigger table activation */
ECS_ENTITY(world, e1, Position);
ECS_ENTITY(world, e2, Position);
/* System is now matched with archetype of entities. Delete entities to
* deactivate table for system */
ecs_delete(world, e1);
ecs_delete(world, e2);
test_assert(true);
ecs_fini(world);
}
void Internals_activate_deactivate_reactive(void) {
ecs_world_t *world = ecs_init();
ECS_COMPONENT(world, Position);
ECS_SYSTEM(world, Iter, EcsOnUpdate, Position);
/* Add entities after system definition to trigger table activation */
ECS_ENTITY(world, e1, Position);
ECS_ENTITY(world, e2, Position);
/* System is now matched with archetype of entities. Delete entities to
* deactivate table for system */
ecs_delete(world, e1);
ecs_delete(world, e2);
/* Add entities of same type to trigger table reactivation */
ECS_ENTITY(world, e3, Position);
ECS_ENTITY(world, e4, Position);
test_assert(true);
ecs_fini(world);
}
void Internals_activate_deactivate_activate_other(void) {
ecs_world_t *world = ecs_init();
ECS_COMPONENT(world, Position);
ECS_COMPONENT(world, Velocity);
ECS_SYSTEM(world, Iter, EcsOnUpdate, Position);
/* Add entities after system definition to trigger table activation */
ECS_ENTITY(world, e1, Position);
ECS_ENTITY(world, e2, Position);
/* System is now matched with archetype of entities. Delete entities to
* deactivate table for system */
ecs_delete(world, e1);
ecs_delete(world, e2);
/* Add entities of different type to trigger new table activation */
ECS_ENTITY(world, e3, Position, Velocity);
ECS_ENTITY(world, e4, Position, Velocity);
test_assert(true);
ecs_fini(world);
}
static int invoked = 0;
static
void CreateNewTable(ecs_iter_t *it) {
ecs_id_t ecs_id(Velocity) = ecs_field_id(it, 2);
int32_t i;
for (i = 0; i < it->count; i ++) {
ecs_add(it->world, it->entities[i], Velocity);
}
}
static
void ManualSystem(ecs_iter_t *it) {
invoked ++;
}
void Internals_no_double_system_table_after_merge(void) {
ecs_world_t *world = ecs_init();
ECS_COMPONENT(world, Position);
ECS_COMPONENT(world, Velocity);
ECS_ENTITY(world, e, Position);
ECS_SYSTEM(world, CreateNewTable, EcsOnUpdate, Position, Velocity());
ECS_SYSTEM(world, ManualSystem, 0, Position, Velocity);
/* CreateNewTable system created a new, non-empty table. This will be merged
* which will trigger activation of ManualSystem. This will cause the system
* to go from the inactive_systems array to the manual_systems array. This
* happens as systems are notified of new tables (during the merge). Because
* the manual_systems array was evaluated after the inactive_systems array,
* a table could be added to a system twice. */
ecs_progress(world, 0);
/* Validate that the CreateNewTable system has ran */
test_assert(ecs_has(world, e, Position));
test_assert(ecs_has(world, e, Velocity));
/* Now run the ManualSystem, and make sure it is only invoked once. If it is
* invoked twice, the table has been registered with the system twice, which
* is wrong. */
ecs_run(world, ManualSystem, 0, NULL);
test_int(invoked, 1);
ecs_fini(world);
}
void Internals_recreate_deleted_table(void) {
ecs_world_t *world = ecs_init();
ECS_COMPONENT(world, Position);
ecs_entity_t parent_A = ecs_new(world, 0);
ecs_entity_t child_A = ecs_new_w_pair(world, EcsChildOf, parent_A);
test_assert(parent_A != 0);
test_assert(child_A != 0);
ecs_delete(world, parent_A); // Deletes table
test_assert( !ecs_is_alive(world, parent_A));
test_assert( !ecs_is_alive(world, child_A));
ecs_entity_t parent_B = ecs_new(world, 0);
ecs_entity_t child_B = ecs_new_w_pair(world, EcsChildOf, parent_B);
test_assert(parent_B != 0);
test_assert(child_B != 0);
ecs_fini(world);
}
void Internals_create_65k_tables(void) {
ecs_world_t *world = ecs_init();
int32_t i;
for (i = 0; i <= 65536; i ++) {
ecs_entity_t e = ecs_new_id(world);
ecs_add_id(world, e, e);
test_assert(ecs_has_id(world, e, e));
test_int(ecs_get_type(world, e)->count, 1);
}
ecs_fini(world);
}
void Internals_no_duplicate_root_table_id(void) {
ecs_world_t *world = ecs_init();
/* This scenario triggered a bug where the first table registered in the
* world would get id 0, which is the same id as the root table. This caused
* the table cache to assert as it saw the wrong table for an id. */
int32_t i;
for (i = 0; i <= 50; i ++) {
ecs_entity_t e = ecs_new_id(world);
ecs_add_id(world, e, i + 1000);
test_assert(e != 0);
test_assert(ecs_has_id(world, e, i + 1000));
}
ecs_entity_t f = ecs_entity_init(world, &(ecs_entity_desc_t){
.name = "Foo"
});
test_assert(f != 0);
test_str(ecs_get_name(world, f), "Foo");
ecs_fini(world);
}
void Internals_override_os_api_w_addon(void) {
ecs_os_set_api_defaults();
ecs_os_api_t os_api = ecs_os_api;
ecs_os_set_api(&os_api);
test_assert(ecs_os_has_threading());
test_assert(ecs_os_has_time());
test_assert(ecs_os_has_logging());
test_assert(ecs_os_has_heap());
ecs_world_t *world = ecs_init();
ecs_fini(world);
}
void Internals_records_resize_on_override(void) {
ecs_world_t *world = ecs_mini();
ecs_entity_t TagA = ecs_new_id(world);
ecs_entity_t TagB = ecs_new_id(world);
ecs_entity_t TagC = ecs_new_id(world);
ecs_entity_t TagD = ecs_new_id(world);
ecs_entity_t TagE = ecs_new_id(world);
ecs_entity_t TagF = ecs_new_id(world);
ecs_entity_t TagG = ecs_new_id(world);
ecs_entity_t TagH = ecs_new_id(world);
ecs_entity_t RelA = ecs_new_id(world);
ecs_entity_t RelB = ecs_new_id(world);
ecs_entity_t RelC = ecs_new_id(world);
ecs_entity_t RelD = ecs_new_id(world);
ecs_entity_t RelE = ecs_new_id(world);
ecs_entity_t RelF = ecs_new_id(world);
ecs_entity_t RelG = ecs_new_id(world);
ecs_entity_t TgtA = ecs_new_id(world);
ecs_entity_t TgtB = ecs_new_id(world);
ecs_entity_t e = ecs_new_id(world);
ecs_add_id(world, e, TagA);
ecs_add_id(world, e, TagB);
ecs_add_id(world, e, TagC);
ecs_add_id(world, e, TagD);
ecs_add_id(world, e, TagE);
ecs_add_id(world, e, TagF);
ecs_add_id(world, e, TagG);
ecs_add_id(world, e, TagH);
ecs_add_pair(world, e, RelA, TgtA);
ecs_add_pair(world, e, RelB, TgtA);
ecs_add_pair(world, e, RelC, TgtA);
ecs_add_pair(world, e, RelD, TgtA);
ecs_add_pair(world, e, RelE, TgtA);
ecs_add_pair(world, e, RelF, TgtA);
ecs_override_pair(world, e, RelG, TgtB);
test_assert(ecs_has_id(world, e, TagA));
test_assert(ecs_has_id(world, e, TagB));
test_assert(ecs_has_id(world, e, TagC));
test_assert(ecs_has_id(world, e, TagD));
test_assert(ecs_has_id(world, e, TagE));
test_assert(ecs_has_id(world, e, TagF));
test_assert(ecs_has_id(world, e, TagG));
test_assert(ecs_has_id(world, e, TagH));
test_assert(ecs_has_pair(world, e, RelA, TgtA));
test_assert(ecs_has_pair(world, e, RelB, TgtA));
test_assert(ecs_has_pair(world, e, RelC, TgtA));
test_assert(ecs_has_pair(world, e, RelD, TgtA));
test_assert(ecs_has_pair(world, e, RelE, TgtA));
test_assert(ecs_has_pair(world, e, RelF, TgtA));
ecs_fini(world);
}
void Internals_table_observed_after_add(void) {
ecs_world_t *world = ecs_mini();
ECS_TAG(world, TagA);
ECS_TAG(world, TagB);
ecs_entity_t p = ecs_new_id(world);
ecs_entity_t c = ecs_new_w_pair(world, EcsChildOf, p);
ecs_table_t *pt = ecs_get_table(world, p);
ecs_table_t *ct = ecs_get_table(world, c);
test_assert(pt == NULL);
test_assert(ct != NULL);
test_int(flecs_table_observed_count(ct), 0);
ecs_add(world, p, TagA);
ecs_table_t *pt_a = ecs_get_table(world, p);
test_assert(pt_a != NULL);
test_int(flecs_table_observed_count(pt_a), 1);
ecs_add(world, p, TagB);
ecs_table_t *pt_b = ecs_get_table(world, p);
test_assert(pt_b != NULL);
test_int(flecs_table_observed_count(pt_a), 0);
test_int(flecs_table_observed_count(pt_b), 1);
ecs_fini(world);
}
void Internals_table_observed_after_remove(void) {
ecs_world_t *world = ecs_mini();
ECS_TAG(world, TagA);
ECS_TAG(world, TagB);
ecs_entity_t p = ecs_new_id(world);
ecs_entity_t c = ecs_new_w_pair(world, EcsChildOf, p);
ecs_table_t *pt = ecs_get_table(world, p);
ecs_table_t *ct = ecs_get_table(world, c);
test_assert(pt == NULL);
test_assert(ct != NULL);
test_int(flecs_table_observed_count(ct), 0);
ecs_add(world, p, TagA);
ecs_table_t *pt_a = ecs_get_table(world, p);
test_assert(pt_a != NULL);
test_int(flecs_table_observed_count(pt_a), 1);
ecs_add(world, p, TagB);
ecs_table_t *pt_b = ecs_get_table(world, p);
test_assert(pt_b != NULL);
test_int(flecs_table_observed_count(pt_a), 0);
test_int(flecs_table_observed_count(pt_b), 1);
ecs_remove(world, p, TagB);
test_int(flecs_table_observed_count(pt_a), 1);
test_int(flecs_table_observed_count(pt_b), 0);
ecs_remove(world, p, TagA);
test_int(flecs_table_observed_count(pt_a), 0);
test_int(flecs_table_observed_count(pt_b), 0);
ecs_fini(world);
}
void Internals_table_observed_after_clear(void) {
ecs_world_t *world = ecs_mini();
ECS_TAG(world, TagA);
ecs_entity_t p = ecs_new_id(world);
ecs_entity_t c = ecs_new_w_pair(world, EcsChildOf, p);
ecs_table_t *pt = ecs_get_table(world, p);
ecs_table_t *ct = ecs_get_table(world, c);
test_assert(pt == NULL);
test_assert(ct != NULL);
test_int(flecs_table_observed_count(ct), 0);
ecs_add(world, p, TagA);
ecs_table_t *pt_a = ecs_get_table(world, p);
test_assert(pt_a != NULL);
test_int(flecs_table_observed_count(pt_a), 1);
ecs_clear(world, p);
test_int(flecs_table_observed_count(pt_a), 0);
ecs_add(world, p, TagA);
test_int(flecs_table_observed_count(pt_a), 1);
ecs_fini(world);
}
void Internals_table_observed_after_delete(void) {
ecs_world_t *world = ecs_mini();
ECS_TAG(world, TagA);
ecs_entity_t p = ecs_new_id(world);
ecs_entity_t c = ecs_new_w_pair(world, EcsChildOf, p);
ecs_table_t *pt = ecs_get_table(world, p);
ecs_table_t *ct = ecs_get_table(world, c);
test_assert(pt == NULL);
test_assert(ct != NULL);
test_int(flecs_table_observed_count(ct), 0);
ecs_add(world, p, TagA);
ecs_table_t *pt_a = ecs_get_table(world, p);
test_assert(pt_a != NULL);
test_int(flecs_table_observed_count(pt_a), 1);
ecs_delete(world, p);
test_int(flecs_table_observed_count(pt_a), 0);
ecs_fini(world);
}
void Internals_table_observed_after_on_remove(void) {
ecs_world_t *world = ecs_mini();
ECS_TAG(world, TagA);
ecs_entity_t p = ecs_new_id(world);
ecs_entity_t c = ecs_new_w_pair(world, EcsChildOf, p);
ecs_table_t *pt = ecs_get_table(world, p);
ecs_table_t *ct = ecs_get_table(world, c);
test_assert(pt == NULL);
test_assert(ct != NULL);
test_int(flecs_table_observed_count(ct), 0);
ecs_entity_t t = ecs_new_id(world);
ecs_add_id(world, p, t);
ecs_table_t *pt_t = ecs_get_table(world, p);
test_assert(pt_t != NULL);
test_int(flecs_table_observed_count(pt_t), 1);
ecs_add(world, p, TagA);
ecs_table_t *pt_ta = ecs_get_table(world, p);
test_assert(pt_ta != NULL);
test_int(flecs_table_observed_count(pt_t), 0);
test_int(flecs_table_observed_count(pt_ta), 1);
ecs_delete(world, t);
test_assert(!ecs_has_id(world, p, t));
test_assert(ecs_has(world, p, TagA));
ecs_table_t *p_a = ecs_get_table(world, p);
test_assert(p_a != NULL);
test_int(flecs_table_observed_count(p_a), 1);
ecs_fini(world);
}
void Internals_table_observed_after_entity_flag(void) {
ecs_world_t *world = ecs_mini();
ECS_TAG(world, TagA);
ECS_TAG(world, TagB);
ecs_entity_t p = ecs_new_id(world);
ecs_add(world, p, TagA);
ecs_table_t *p_a = ecs_get_table(world, p);
test_assert(p_a != NULL);
test_int(flecs_table_observed_count(p_a), 0);
ecs_entity_t c = ecs_new_w_pair(world, EcsChildOf, p);
ecs_table_t *ct = ecs_get_table(world, c);
test_assert(ct != NULL);
test_int(flecs_table_observed_count(ct), 0);
test_int(flecs_table_observed_count(p_a), 1);
ecs_fini(world);
}
void Internals_table_create_leak_check(void) {
ecs_world_t *world = ecs_mini();
int64_t max_block_count;
ecs_entity_t tag = ecs_new_id(world);
ecs_entity_t e = ecs_new_w_id(world, tag);
max_block_count = ecs_block_allocator_alloc_count -
ecs_block_allocator_free_count;
ecs_delete(world, tag);
for (int i = 0; i < 25000; i ++) {
tag = ecs_new_id(world);
ecs_add_id(world, e, tag);
ecs_delete(world, tag);
}
test_int(max_block_count, ecs_block_allocator_alloc_count -
ecs_block_allocator_free_count);
ecs_fini(world);
}

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,666 @@
#include <api.h>
#include <stdio.h>
void Lookup_setup(void) {
ecs_log_set_level(-3);
}
void Lookup_lookup(void) {
ecs_world_t *world = ecs_mini();
ECS_ENTITY(world, MyEntity, 0);
ecs_entity_t lookup = ecs_lookup(world, "MyEntity");
test_assert(lookup != 0);
test_assert(lookup == MyEntity);
ecs_fini(world);
}
void Lookup_lookup_w_null_name(void) {
ecs_world_t *world = ecs_mini();
ECS_ENTITY(world, MyEntity, 0);
/* Ensure this doesn't crash the lookup function */
ecs_set_name(world, 0, NULL);
ecs_entity_t lookup = ecs_lookup(world, "MyEntity");
test_assert(lookup != 0);
test_assert(lookup == MyEntity);
ecs_fini(world);
}
void Lookup_lookup_after_name_reset(void) {
ecs_world_t *world = ecs_mini();
ecs_entity_t e = ecs_new_entity(world, "foo");
ecs_entity_t lookup = ecs_lookup(world, "foo");
test_assert(e == lookup);
ecs_set_name(world, e, NULL);
test_assert(ecs_lookup(world, "foo") == 0);
ecs_set_name(world, e, "foo");
lookup = ecs_lookup(world, "foo");
test_assert(e == lookup);
ecs_fini(world);
}
void Lookup_lookup_component(void) {
ecs_world_t *world = ecs_mini();
ECS_COMPONENT(world, Position);
ecs_entity_t lookup = ecs_lookup(world, "Position");
test_assert(lookup != 0);
test_assert(lookup == ecs_id(Position));
ecs_fini(world);
}
void Lookup_lookup_not_found(void) {
ecs_world_t *world = ecs_mini();
ecs_entity_t lookup = ecs_lookup(world, "foo");
test_assert(lookup == 0);
ecs_fini(world);
}
void Lookup_lookup_child(void) {
ecs_world_t *world = ecs_mini();
ECS_ENTITY(world, Parent1, 0);
ECS_ENTITY(world, Parent2, 0);
ecs_entity_t e1 = ecs_new_w_pair(world, EcsChildOf, Parent1);
ecs_set_name(world, e1, "Child");
ecs_entity_t e2 = ecs_new_w_pair(world, EcsChildOf, Parent2);
ecs_set_name(world, e2, "Child");
ecs_add_pair(world, e1, EcsChildOf, Parent1);
ecs_add_pair(world, e2, EcsChildOf, Parent2);
ecs_entity_t lookup = ecs_lookup_child(world, Parent1, "Child");
test_assert(lookup != 0);
test_assert(lookup == e1);
lookup = ecs_lookup_child(world, Parent2, "Child");
test_assert(lookup != 0);
test_assert(lookup == e2);
ecs_fini(world);
}
void Lookup_get_name(void) {
ecs_world_t *world = ecs_mini();
/* Ensure this doesn't crash the lookup function */
ecs_entity_t e = ecs_set_name(world, 0, "Entity");
const char *id = ecs_get_name(world, e);
test_assert(id != NULL);
test_str(id, "Entity");
ecs_fini(world);
}
void Lookup_get_name_no_name(void) {
ecs_world_t *world = ecs_mini();
ECS_COMPONENT(world, Position);
/* Ensure this doesn't crash the lookup function */
ecs_entity_t e = ecs_new(world, Position);
const char *id = ecs_get_name(world, e);
test_assert(id == NULL);
ecs_fini(world);
}
void Lookup_get_name_from_empty(void) {
ecs_world_t *world = ecs_mini();
/* Ensure this doesn't crash the lookup function */
ecs_entity_t e = ecs_new(world, 0);
const char *id = ecs_get_name(world, e);
test_assert(id == NULL);
ecs_fini(world);
}
void Lookup_lookup_by_id(void) {
ecs_world_t *world = ecs_mini();
ecs_entity_t e = ecs_lookup(world, "1000");
test_int(e, 1000);
ecs_fini(world);
}
void Lookup_lookup_recycled_by_id(void) {
ecs_world_t *world = ecs_mini();
ecs_entity_t e = ecs_new_id(world);
test_assert(e != 0);
char buf[20];
sprintf(buf, "%u", (uint32_t)e);
ecs_entity_t l = ecs_lookup(world, buf);
test_assert(l != 0);
test_assert(l == e);
ecs_delete(world, e);
ecs_entity_t r = ecs_new_id(world);
test_assert((uint32_t)r == e);
test_assert(r != e);
l = ecs_lookup(world, buf);
test_assert(l == r);
ecs_fini(world);
}
void Lookup_lookup_name_w_digit(void) {
ecs_world_t *world = ecs_mini();
ecs_entity_t e = ecs_set_name(world, 0, "10_id");
ecs_entity_t e2 = ecs_lookup(world, "10_id");
test_assert(e == e2);
ecs_fini(world);
}
void Lookup_lookup_symbol_by_id(void) {
ecs_world_t *world = ecs_mini();
ecs_ensure(world, 1000);
ecs_entity_t e = ecs_lookup_symbol(world, "1000", true, true);
test_int(e, 1000);
ecs_fini(world);
}
void Lookup_lookup_symbol_w_digit(void) {
ecs_world_t *world = ecs_mini();
ecs_entity_t e = ecs_set_symbol(world, 0, "10_id");
ecs_entity_t e2 = ecs_lookup_symbol(world, "10_id", true, true);
test_assert(e == e2);
ecs_fini(world);
}
void Lookup_lookup_path_w_digit(void) {
ecs_world_t *world = ecs_mini();
ecs_entity_t parent = ecs_set_name(world, 0, "parent");
ecs_entity_t e1 = ecs_set_name(world, 0, "10_id");
ecs_add_pair(world, e1, EcsChildOf, parent);
ecs_entity_t e2 = ecs_lookup_fullpath(world, "parent.10_id");
test_assert(e2 == e1);
ecs_fini(world);
}
void Lookup_set_name_of_existing(void) {
ecs_world_t *world = ecs_mini();
ecs_entity_t e = ecs_new(world, 0);
test_assert(e != 0);
test_assert(ecs_get_name(world, e) == NULL);
ecs_set_name(world, e, "Foo");
test_assert(ecs_get_name(world, e) != NULL);
test_str(ecs_get_name(world, e), "Foo");
ecs_fini(world);
}
void Lookup_change_name_of_existing(void) {
ecs_world_t *world = ecs_mini();
ecs_entity_t e = ecs_set_name(world, 0, "Foo");
test_assert(e != 0);
test_assert(ecs_get_name(world, e) != NULL);
test_str(ecs_get_name(world, e), "Foo");
ecs_set_name(world, e, "Bar");
test_assert(ecs_get_name(world, e) != NULL);
test_str(ecs_get_name(world, e), "Bar");
ecs_fini(world);
}
void Lookup_lookup_alias(void) {
ecs_world_t *world = ecs_mini();
ecs_entity_t e = ecs_set_name(world, 0, "MyEntity");
test_assert(e != 0);
ecs_set_alias(world, e, "MyAlias");
ecs_entity_t a = ecs_lookup(world, "MyAlias");
test_assert(a != 0);
test_assert(a == e);
ecs_fini(world);
}
void Lookup_lookup_scoped_alias(void) {
ecs_world_t *world = ecs_mini();
ecs_entity_t p = ecs_set_name(world, 0, "MyParent");
test_assert(p != 0);
ecs_entity_t e = ecs_set_name(world, 0, "MyEntity");
test_assert(e != 0);
ecs_add_pair(world, e, EcsChildOf, p);
ecs_set_alias(world, e, "MyAlias");
ecs_entity_t a = ecs_lookup(world, "MyAlias");
test_assert(a != 0);
test_assert(a == e);
ecs_fini(world);
}
void Lookup_define_duplicate_alias(void) {
install_test_abort();
ecs_world_t *world = ecs_mini();
ecs_entity_t e1 = ecs_set_name(world, 0, "MyEntityA");
test_assert(e1 != 0);
ecs_entity_t e2 = ecs_set_name(world, 0, "MyEntityB");
test_assert(e2 != 0);
test_expect_abort(); /* Not allowed to create duplicate aliases */
ecs_set_alias(world, e1, "MyAlias");
ecs_set_alias(world, e2, "MyAlias");
}
void Lookup_lookup_null(void) {
ecs_world_t *world = ecs_mini();
test_assert(ecs_lookup(world, NULL) == 0);
ecs_fini(world);
}
void Lookup_lookup_symbol_null(void) {
ecs_world_t *world = ecs_mini();
test_assert(ecs_lookup_symbol(world, NULL, true, true) == 0);
ecs_fini(world);
}
void Lookup_lookup_this(void) {
ecs_world_t *world = ecs_mini();
ecs_entity_t lookup = ecs_lookup(world, ".");
test_assert(lookup != 0);
test_assert(lookup == EcsThis);
ecs_fini(world);
}
void Lookup_lookup_wildcard(void) {
ecs_world_t *world = ecs_mini();
ecs_entity_t lookup = ecs_lookup(world, "*");
test_assert(lookup != 0);
test_assert(lookup == EcsWildcard);
ecs_fini(world);
}
void Lookup_lookup_any(void) {
ecs_world_t *world = ecs_mini();
ecs_entity_t lookup = ecs_lookup(world, "_");
test_assert(lookup != 0);
test_assert(lookup == EcsAny);
ecs_fini(world);
}
void Lookup_lookup_variable(void) {
ecs_world_t *world = ecs_mini();
ecs_entity_t lookup = ecs_lookup(world, "$");
test_assert(lookup != 0);
test_assert(lookup == EcsVariable);
ecs_fini(world);
}
void Lookup_lookup_path_this(void) {
ecs_world_t *world = ecs_mini();
ecs_entity_t lookup = ecs_lookup_path_w_sep(world, 0, ".", NULL, NULL, false);
test_assert(lookup != 0);
test_assert(lookup == EcsThis);
ecs_fini(world);
}
void Lookup_lookup_path_wildcard(void) {
ecs_world_t *world = ecs_mini();
ecs_entity_t lookup = ecs_lookup_path_w_sep(world, 0, "*", NULL, NULL, false);
test_assert(lookup != 0);
test_assert(lookup == EcsWildcard);
ecs_fini(world);
}
void Lookup_lookup_path_this_from_scope(void) {
ecs_world_t *world = ecs_mini();
ecs_entity_t scope = ecs_new_id(world);
ecs_entity_t lookup = ecs_lookup_path_w_sep(world, scope, ".", NULL, NULL, false);
test_assert(lookup != 0);
test_assert(lookup == EcsThis);
ecs_fini(world);
}
void Lookup_lookup_path_wildcard_from_scope(void) {
ecs_world_t *world = ecs_mini();
ecs_entity_t scope = ecs_new_id(world);
ecs_entity_t lookup = ecs_lookup_path_w_sep(world, scope, ".", NULL, NULL, false);
test_assert(lookup != 0);
test_assert(lookup == EcsThis);
ecs_fini(world);
}
void Lookup_resolve_builtin_symbols(void) {
ecs_world_t *world = ecs_mini();
test_assert(ecs_lookup_symbol(world, "EcsComponent", false, true) == ecs_id(EcsComponent));
test_assert(ecs_lookup_symbol(world, "EcsIdentifier", false, true) == ecs_id(EcsIdentifier));
test_assert(ecs_lookup_symbol(world, "EcsName", false, true) == EcsName);
test_assert(ecs_lookup_symbol(world, "EcsSymbol", false, true) == EcsSymbol);
ecs_fini(world);
}
void Lookup_lookup_from_scope_staged(void) {
ecs_world_t *world = ecs_mini();
ecs_entity_t parent = ecs_set_name(world, 0, "Parent");
ecs_entity_t child = ecs_set_name(world, 0, "Child");
ecs_add_pair(world, child, EcsChildOf, parent);
ecs_readonly_begin(world);
ecs_world_t *stage = ecs_get_stage(world, 0);
test_assert(ecs_set_scope(stage, parent) == 0);
test_assert(ecs_lookup_path(stage, 0, "Child") == child);
test_assert(ecs_lookup_fullpath(stage, "Child") == child);
test_assert(ecs_lookup_path(stage, parent, "Child") == child);
test_assert(ecs_lookup_fullpath(stage, "Child") == child);
test_assert(ecs_set_scope(stage, 0) == parent);
ecs_readonly_end(world);
ecs_fini(world);
}
void Lookup_lookup_core(void) {
ecs_world_t *world = ecs_mini();
ecs_entity_t c = ecs_lookup_fullpath(world, "Component");
test_assert(c != 0);
test_assert(c == ecs_id(EcsComponent));
ecs_fini(world);
}
void Lookup_lookup_core_from_stage(void) {
ecs_world_t *world = ecs_mini();
ecs_entity_t c = ecs_lookup_fullpath(world, "Component");
test_assert(c != 0);
test_assert(c == ecs_id(EcsComponent));
ecs_world_t *stage = ecs_get_stage(world, 0);
ecs_readonly_begin(world);
ecs_entity_t d = ecs_lookup_fullpath(stage, "Component");
test_assert(d != 0);
test_assert(d == ecs_id(EcsComponent));
ecs_readonly_end(world);
ecs_entity_t e = ecs_lookup_fullpath(world, "Component");
test_assert(e != 0);
test_assert(e == ecs_id(EcsComponent));
ecs_fini(world);
}
void Lookup_lookup_custom_search_path(void) {
ecs_world_t *world = ecs_mini();
ecs_entity_t parent = ecs_set_name(world, 0, "Parent");
ecs_entity_t child = ecs_new_w_pair(world, EcsChildOf, parent);
ecs_set_name(world, child, "Child");
test_assert(ecs_lookup_fullpath(world, "Parent") == parent);
test_assert(ecs_lookup_fullpath(world, "Child") == 0);
test_assert(ecs_lookup_fullpath(world, "Parent.Child") == child);
ecs_entity_t lookup_path[] = { parent, 0 };
ecs_entity_t *old_path = ecs_set_lookup_path(world, lookup_path);
test_assert(ecs_lookup_fullpath(world, "Parent") == parent);
test_assert(ecs_lookup_fullpath(world, "Child") == child);
test_assert(ecs_lookup_fullpath(world, "Parent.Child") == child);
ecs_set_lookup_path(world, old_path);
ecs_fini(world);
}
void Lookup_lookup_custom_search_path_from_stage(void) {
ecs_world_t *world = ecs_mini();
ecs_entity_t parent = ecs_set_name(world, 0, "Parent");
ecs_entity_t child = ecs_new_w_pair(world, EcsChildOf, parent);
ecs_set_name(world, child, "Child");
test_assert(ecs_lookup_fullpath(world, "Parent") == parent);
test_assert(ecs_lookup_fullpath(world, "Child") == 0);
test_assert(ecs_lookup_fullpath(world, "Parent.Child") == child);
ecs_entity_t lookup_path[] = { parent, 0 };
ecs_entity_t *old_path = ecs_set_lookup_path(world, lookup_path);
ecs_world_t *stage = ecs_get_stage(world, 0);
ecs_readonly_begin(world);
test_assert(ecs_lookup_fullpath(stage, "Parent") == parent);
test_assert(ecs_lookup_fullpath(stage, "Child") == child);
test_assert(ecs_lookup_fullpath(stage, "Parent.Child") == child);
ecs_readonly_end(world);
ecs_set_lookup_path(world, old_path);
ecs_fini(world);
}
void Lookup_lookup_custom_search_path_n_elems(void) {
ecs_world_t *world = ecs_mini();
ecs_entity_t parent = ecs_set_name(world, 0, "Parent");
ecs_entity_t child = ecs_new_w_pair(world, EcsChildOf, parent);
ecs_set_name(world, child, "Child");
ecs_entity_t grand_child = ecs_new_w_pair(world, EcsChildOf, child);
ecs_set_name(world, grand_child, "Child");
test_assert(ecs_lookup_fullpath(world, "Parent") == parent);
test_assert(ecs_lookup_fullpath(world, "Child") == 0);
test_assert(ecs_lookup_fullpath(world, "Child.Child") == 0);
test_assert(ecs_lookup_fullpath(world, "Parent.Child") == child);
test_assert(ecs_lookup_fullpath(world, "Parent.Child.Child") == grand_child);
ecs_entity_t lookup_path[] = { child, parent, 0 };
ecs_entity_t *old_path = ecs_set_lookup_path(world, lookup_path);
test_assert(ecs_lookup_fullpath(world, "Parent") == parent);
test_assert(ecs_lookup_fullpath(world, "Child") == child);
test_assert(ecs_lookup_fullpath(world, "Child.Child") == grand_child);
test_assert(ecs_lookup_fullpath(world, "Parent.Child") == child);
test_assert(ecs_lookup_fullpath(world, "Parent.Child.Child") == grand_child);
lookup_path[0] = parent;
lookup_path[1] = child;
test_assert(ecs_lookup_fullpath(world, "Parent") == parent);
test_assert(ecs_lookup_fullpath(world, "Child") == grand_child);
test_assert(ecs_lookup_fullpath(world, "Child.Child") == grand_child);
test_assert(ecs_lookup_fullpath(world, "Parent.Child") == child);
test_assert(ecs_lookup_fullpath(world, "Parent.Child.Child") == grand_child);
ecs_set_lookup_path(world, old_path);
ecs_fini(world);
}
void Lookup_set_same_name(void) {
ecs_world_t *world = ecs_mini();
ecs_entity_t e = ecs_new_entity(world, "MyName");
test_assert(e != 0);
test_str("MyName", ecs_get_name(world, e));
test_uint(e, ecs_lookup(world, "MyName"));
ecs_set_name(world, e, "MyName");
test_str("MyName", ecs_get_name(world, e));
test_uint(e, ecs_lookup(world, "MyName"));
ecs_fini(world);
}
void Lookup_set_same_name_after_reparenting(void) {
ecs_world_t *world = ecs_mini();
ecs_entity_t parent = ecs_new_entity(world, "parent");
ecs_entity_t e = ecs_new_entity(world, "MyName");
test_assert(e != 0);
test_str("MyName", ecs_get_name(world, e));
test_uint(e, ecs_lookup(world, "MyName"));
ecs_add_pair(world, e, EcsChildOf, parent);
test_str("MyName", ecs_get_name(world, e));
test_uint(e, ecs_lookup_fullpath(world, "parent.MyName"));
ecs_set_name(world, e, "MyName");
test_str("MyName", ecs_get_name(world, e));
test_uint(e, ecs_lookup_fullpath(world, "parent.MyName"));
ecs_fini(world);
}
void Lookup_defer_set_name(void) {
ecs_world_t *world = ecs_mini();
ecs_entity_t e = ecs_new_entity(world, "Foo");
test_assert(e != 0);
test_str("Foo", ecs_get_name(world, e));
test_uint(e, ecs_lookup(world, "Foo"));
ecs_defer_begin(world);
ecs_set_name(world, e, "Bar");
ecs_defer_end(world);
test_str("Bar", ecs_get_name(world, e));
test_uint(e, ecs_lookup(world, "Bar"));
ecs_fini(world);
}
void Lookup_defer_set_same_name(void) {
ecs_world_t *world = ecs_mini();
ecs_entity_t e = ecs_new_entity(world, "MyName");
test_assert(e != 0);
test_str("MyName", ecs_get_name(world, e));
test_uint(e, ecs_lookup(world, "MyName"));
ecs_defer_begin(world);
ecs_set_name(world, e, "MyName");
ecs_defer_end(world);
test_str("MyName", ecs_get_name(world, e));
test_uint(e, ecs_lookup(world, "MyName"));
ecs_fini(world);
}
void Lookup_lookup_invalid_digit(void) {
ecs_world_t *world = ecs_mini();
ecs_entity_t child = ecs_lookup(world, "111111111111");
test_assert(child == 0);
ecs_fini(world);
}
void Lookup_lookup_child_invalid_digit(void) {
ecs_world_t *world = ecs_mini();
ecs_entity_t parent = ecs_new_entity(world, "p");
test_assert(parent != 0);
ecs_entity_t child = ecs_lookup_child(world, parent, "111111111111");
test_assert(child == 0);
ecs_fini(world);
}
void Lookup_lookup_digit_from_wrong_scope(void) {
ecs_world_t *world = ecs_mini();
ecs_entity_t parent = ecs_new_entity(world, "p");
test_assert(parent != 0);
ecs_entity_t child = ecs_lookup_fullpath(world, "p.1");
test_assert(child == 0);
ecs_fini(world);
}
void Lookup_lookup_core_entity_from_wrong_scope(void) {
ecs_world_t *world = ecs_mini();
ecs_entity_t parent = ecs_new_entity(world, "p");
test_assert(parent != 0);
ecs_entity_t child = ecs_lookup_fullpath(world, "p.10.Component");
test_assert(child == 0);
ecs_fini(world);
}
void Lookup_lookup_alias_w_number(void) {
ecs_world_t *world = ecs_mini();
ecs_entity_t parent = ecs_new_entity(world, "p");
test_assert(parent != 0);
ecs_set_alias(world, parent, "10p");
test_assert(parent == ecs_lookup_fullpath(world, "p"));
test_assert(parent == ecs_lookup_fullpath(world, "10p"));
ecs_fini(world);
}

View File

@@ -0,0 +1,729 @@
#include <api.h>
static
void OnPosition(ecs_iter_t *it) {
probe_iter(it);
}
void Monitor_1_comp(void) {
ecs_world_t *world = ecs_mini();
ECS_COMPONENT(world, Position);
ECS_COMPONENT(world, Velocity);
ECS_OBSERVER(world, OnPosition, EcsOnAdd, Position);
Probe ctx = { 0 };
ecs_set_ctx(world, &ctx, NULL);
ecs_entity_t e = ecs_new(world, Position);
test_int(ctx.invoked, 1);
test_int(ctx.count, 1);
test_int(ctx.system, OnPosition);
test_int(ctx.term_count, 1);
test_null(ctx.param);
test_int(ctx.e[0], e);
test_int(ctx.c[0][0], ecs_id(Position));
test_int(ctx.s[0][0], 0);
ecs_os_zeromem(&ctx);
ecs_run_aperiodic(world, 0);
test_int(ctx.invoked, 0);
ecs_add(world, e, Velocity);
test_int(ctx.invoked, 0);
ecs_fini(world);
}
void Monitor_2_comps(void) {
ecs_world_t *world = ecs_mini();
ECS_COMPONENT(world, Position);
ECS_COMPONENT(world, Velocity);
ECS_OBSERVER(world, OnPosition, EcsOnAdd, Position, Velocity);
Probe ctx = { 0 };
ecs_set_ctx(world, &ctx, NULL);
ecs_entity_t e = ecs_new(world, Position);
test_int(ctx.invoked, 0);
ecs_add(world, e, Velocity);
test_int(ctx.invoked, 1);
test_int(ctx.count, 1);
test_int(ctx.system, OnPosition);
test_int(ctx.term_count, 2);
test_null(ctx.param);
test_int(ctx.e[0], e);
test_int(ctx.c[0][0], ecs_id(Position));
test_int(ctx.s[0][0], 0);
test_int(ctx.c[0][1], ecs_id(Velocity));
test_int(ctx.s[0][1], 0);
ecs_os_zeromem(&ctx);
ecs_remove(world, e, Position);
test_int(ctx.invoked, 0);
ecs_add(world, e, Position);
test_int(ctx.invoked, 1);
test_int(ctx.count, 1);
test_int(ctx.system, OnPosition);
test_int(ctx.term_count, 2);
test_null(ctx.param);
test_int(ctx.e[0], e);
test_int(ctx.c[0][0], ecs_id(Position));
test_int(ctx.s[0][0], 0);
test_int(ctx.c[0][1], ecs_id(Velocity));
test_int(ctx.s[0][1], 0);
ecs_fini(world);
}
void Monitor_1_comp_1_not(void) {
ecs_world_t *world = ecs_mini();
ECS_COMPONENT(world, Position);
ECS_COMPONENT(world, Velocity);
ECS_OBSERVER(world, OnPosition, EcsOnAdd, Position, !Velocity);
Probe ctx = { 0 };
ecs_set_ctx(world, &ctx, NULL);
ecs_entity_t e = ecs_new(world, Position);
test_int(ctx.invoked, 1);
test_int(ctx.count, 1);
test_int(ctx.system, OnPosition);
test_int(ctx.term_count, 2);
test_null(ctx.param);
test_int(ctx.e[0], e);
test_int(ctx.c[0][0], ecs_id(Position));
test_int(ctx.s[0][0], 0);
test_int(ctx.c[0][1], ecs_id(Velocity));
test_int(ctx.s[0][1], 0);
ecs_os_zeromem(&ctx);
ecs_add(world, e, Velocity);
test_int(ctx.invoked, 0);
ecs_remove(world, e, Velocity);
test_int(ctx.invoked, 1);
test_int(ctx.count, 1);
test_int(ctx.system, OnPosition);
test_int(ctx.term_count, 2);
test_null(ctx.param);
test_int(ctx.e[0], e);
test_int(ctx.c[0][0], ecs_id(Position));
test_int(ctx.s[0][0], 0);
test_int(ctx.c[0][1], ecs_id(Velocity));
test_int(ctx.s[0][1], 0);
ecs_fini(world);
}
void Monitor_1_parent(void) {
ecs_world_t *world = ecs_mini();
ECS_COMPONENT(world, Position);
ECS_COMPONENT(world, Velocity);
ECS_OBSERVER(world, OnPosition, EcsOnAdd, Position(parent));
Probe ctx = { 0 };
ecs_set_ctx(world, &ctx, NULL);
ecs_entity_t parent = ecs_new(world, Position);
test_int(ctx.invoked, 0);
ecs_entity_t e = ecs_new(world, 0);
test_int(ctx.invoked, 0);
ecs_add_pair(world, e, EcsChildOf, parent);
test_int(ctx.invoked, 1);
test_int(ctx.count, 1);
test_int(ctx.system, OnPosition);
test_int(ctx.term_count, 1);
test_null(ctx.param);
test_int(ctx.e[0], e);
test_int(ctx.c[0][0], ecs_id(Position));
test_int(ctx.s[0][0], parent);
ecs_fini(world);
}
void Monitor_1_comp_1_parent(void) {
ecs_world_t *world = ecs_mini();
ECS_COMPONENT(world, Position);
ECS_COMPONENT(world, Velocity);
ECS_OBSERVER(world, OnPosition, EcsMonitor,
Position, Position(up(ChildOf)));
Probe ctx = { 0 };
ecs_set_ctx(world, &ctx, NULL);
ecs_entity_t parent = ecs_new(world, Position);
test_int(ctx.invoked, 0);
ecs_entity_t e = ecs_new(world, Position);
test_int(ctx.invoked, 0);
ecs_add_pair(world, e, EcsChildOf, parent);
test_int(ctx.invoked, 1);
test_int(ctx.count, 1);
test_int(ctx.event, EcsOnAdd);
test_int(ctx.system, OnPosition);
test_int(ctx.term_count, 2);
test_null(ctx.param);
test_int(ctx.e[0], e);
test_int(ctx.c[0][0], ecs_id(Position));
test_int(ctx.s[0][0], 0);
test_int(ctx.c[0][1], ecs_id(Position));
test_int(ctx.s[0][1], parent);
ecs_os_zeromem(&ctx);
ecs_add(world, e, Velocity);
test_int(ctx.invoked, 0);
ecs_remove(world, e, Velocity);
test_int(ctx.invoked, 0);
ecs_remove(world, e, Position);
test_int(ctx.invoked, 1);
test_int(ctx.count, 1);
test_int(ctx.event, EcsOnRemove);
ecs_os_zeromem(&ctx);
ecs_add(world, e, Position);
test_int(ctx.invoked, 1);
test_int(ctx.count, 1);
test_int(ctx.event, EcsOnAdd);
test_int(ctx.system, OnPosition);
test_int(ctx.term_count, 2);
test_null(ctx.param);
test_int(ctx.e[0], e);
test_int(ctx.c[0][0], ecs_id(Position));
test_int(ctx.s[0][0], 0);
test_int(ctx.c[0][1], ecs_id(Position));
test_int(ctx.s[0][1], parent);
ecs_fini(world);
}
void Monitor_1_comp_prefab_new(void) {
ecs_world_t *world = ecs_mini();
ECS_COMPONENT(world, Position);
ECS_COMPONENT(world, Velocity);
ECS_OBSERVER(world, OnPosition, EcsOnAdd, Position);
Probe ctx = { 0 };
ecs_set_ctx(world, &ctx, NULL);
ECS_PREFAB(world, Prefab, Position);
test_int(ctx.invoked, 0);
ecs_run_aperiodic(world, 0);
test_int(ctx.invoked, 0);
ecs_add(world, Prefab, Velocity);
test_int(ctx.invoked, 0);
ecs_fini(world);
}
void Monitor_1_comp_prefab_add(void) {
ecs_world_t *world = ecs_mini();
ECS_COMPONENT(world, Position);
ECS_COMPONENT(world, Velocity);
ECS_OBSERVER(world, OnPosition, EcsOnAdd, Position);
Probe ctx = { 0 };
ecs_set_ctx(world, &ctx, NULL);
ecs_entity_t e = ecs_new_w_id(world, EcsPrefab);
ecs_add(world, e, Position);
test_int(ctx.invoked, 0);
ecs_run_aperiodic(world, 0);
test_int(ctx.invoked, 0);
ecs_add(world, e, Velocity);
test_int(ctx.invoked, 0);
ecs_fini(world);
}
void Monitor_monitor_w_and(void) {
ecs_world_t *world = ecs_mini();
ECS_COMPONENT(world, Position);
ECS_COMPONENT(world, Velocity);
ECS_COMPONENT(world, Mass);
ECS_OBSERVER(world, OnPosition, EcsMonitor, Position, Velocity);
Probe ctx = { 0 };
ecs_set_ctx(world, &ctx, NULL);
ecs_entity_t e = ecs_new(world, Position);
test_assert(e != 0);
test_int(ctx.invoked, 0);
ecs_add(world, e, Velocity);
test_int(ctx.invoked, 1); // First match, trigger OnAdd
test_int(ctx.event, EcsOnAdd);
ecs_os_zeromem(&ctx);
ecs_remove(world, e, Velocity);
test_int(ctx.invoked, 1); // First unmatch, trigger OnRemove
test_int(ctx.event, EcsOnRemove);
ecs_os_zeromem(&ctx);
ecs_remove(world, e, Position);
test_int(ctx.invoked, 0); // Second unmatch, no trigger
ecs_add(world, e, Velocity);
test_int(ctx.invoked, 0);
ecs_add(world, e, Position);
test_int(ctx.invoked, 1); // First match, trigger OnAdd
test_int(ctx.event, EcsOnAdd);
ecs_fini(world);
}
void Monitor_monitor_w_or(void) {
ecs_world_t *world = ecs_mini();
ECS_COMPONENT(world, Position);
ECS_COMPONENT(world, Velocity);
ECS_COMPONENT(world, Mass);
ECS_OBSERVER(world, OnPosition, EcsMonitor, Position, Velocity || Mass);
Probe ctx = { 0 };
ecs_set_ctx(world, &ctx, NULL);
ecs_entity_t e = ecs_new(world, Position);
test_assert(e != 0);
test_int(ctx.invoked, 0); // No match, filter doesn't match yet
ecs_add(world, e, Velocity);
test_int(ctx.invoked, 1); // First match, triggers OnAdd
test_int(ctx.event, EcsOnAdd);
ecs_os_zeromem(&ctx);
ecs_add(world, e, Mass);
test_int(ctx.invoked, 0); // Second match, no trigger
ecs_remove(world, e, Position);
test_int(ctx.invoked, 1); // First non-match, triggers OnRemove
test_int(ctx.event, EcsOnRemove);
ecs_os_zeromem(&ctx);
ecs_add(world, e, Position); // First match, trigger
test_int(ctx.invoked, 1);
test_int(ctx.event, EcsOnAdd);
ecs_fini(world);
}
void Monitor_monitor_w_not(void) {
ecs_world_t *world = ecs_mini();
ECS_COMPONENT(world, Position);
ECS_COMPONENT(world, Velocity);
ECS_COMPONENT(world, Mass);
ECS_OBSERVER(world, OnPosition, EcsMonitor, Position, Mass, !Velocity);
Probe ctx = { 0 };
ecs_set_ctx(world, &ctx, NULL);
ecs_entity_t e = ecs_new(world, Position);
test_assert(e != 0);
test_int(ctx.invoked, 0);
ecs_add(world, e, Mass);
test_int(ctx.invoked, 1); // First match, trigger OnAdd
test_int(ctx.event, EcsOnAdd);
ecs_os_zeromem(&ctx);
ecs_add(world, e, Velocity);
test_int(ctx.invoked, 1); // First unmatch, trigger OnRemove
test_int(ctx.event, EcsOnRemove);
ecs_os_zeromem(&ctx);
ecs_remove(world, e, Velocity);
test_int(ctx.invoked, 1); // First match, trigger OnAdd
test_int(ctx.event, EcsOnAdd);
ecs_fini(world);
}
void Monitor_monitor_w_optional(void) {
ecs_world_t *world = ecs_mini();
ECS_COMPONENT(world, Position);
ECS_COMPONENT(world, Velocity);
ECS_COMPONENT(world, Mass);
ECS_OBSERVER(world, OnPosition, EcsMonitor, Position, ?Velocity);
Probe ctx = { 0 };
ecs_set_ctx(world, &ctx, NULL);
ecs_entity_t e = ecs_new(world, Position);
test_assert(e != 0);
test_int(ctx.invoked, 1); // First match, trigger OnAdd
test_int(ctx.event, EcsOnAdd);
ecs_os_zeromem(&ctx);
ecs_add(world, e, Velocity);
test_int(ctx.invoked, 0); // Second match, no trigger
ecs_remove(world, e, Position);
test_int(ctx.invoked, 1); // First unmatch, trigger OnRemove
test_int(ctx.event, EcsOnRemove);
ecs_os_zeromem(&ctx);
ecs_add(world, e, Position);
test_int(ctx.invoked, 1); // First match, trigger OnAdd
test_int(ctx.event, EcsOnAdd);
ecs_os_zeromem(&ctx);
ecs_remove(world, e, Velocity);
test_int(ctx.invoked, 0); // Second match, no trigger
ecs_fini(world);
}
void Monitor_monitor_w_superset(void) {
ecs_world_t *world = ecs_mini();
ECS_COMPONENT(world, Position);
ECS_COMPONENT(world, Velocity);
ECS_COMPONENT(world, Mass);
ECS_OBSERVER(world, OnPosition, EcsMonitor, Position, Velocity(up));
Probe ctx = { 0 };
ecs_set_ctx(world, &ctx, NULL);
ecs_entity_t base_1 = ecs_new(world, Velocity);
test_assert(base_1 != 0);
test_int(ctx.invoked, 0);
ecs_entity_t base_2 = ecs_new(world, Velocity);
test_assert(base_2 != 0);
test_int(ctx.invoked, 0);
ecs_entity_t e = ecs_new(world, Position);
test_assert(e != 0);
test_int(ctx.invoked, 0);
ecs_add_pair(world, e, EcsIsA, base_1);
test_int(ctx.invoked, 1); // First match, trigger
test_int(ctx.event, EcsOnAdd);
ecs_os_zeromem(&ctx);
ecs_add_pair(world, e, EcsIsA, base_2);
test_int(ctx.invoked, 0); // Second match, no trigger
ecs_remove_pair(world, e, EcsIsA, base_2);
test_int(ctx.invoked, 0);
ecs_remove_pair(world, e, EcsIsA, base_1);
test_int(ctx.invoked, 1); // First unmatch, trigger OnRemove
test_int(ctx.event, EcsOnRemove);
ecs_os_zeromem(&ctx);
ecs_remove(world, e, Position);
test_int(ctx.invoked, 0); // Second unmatch, no trigger
ecs_fini(world);
}
void Monitor_monitor_w_self_superset(void) {
ecs_world_t *world = ecs_mini();
ECS_COMPONENT(world, Position);
ECS_COMPONENT(world, Velocity);
ECS_COMPONENT(world, Mass);
ECS_OBSERVER(world, OnPosition, EcsMonitor, Position, Velocity(self|up));
Probe ctx = { 0 };
ecs_set_ctx(world, &ctx, NULL);
ecs_entity_t base_1 = ecs_new(world, Velocity);
test_assert(base_1 != 0);
test_int(ctx.invoked, 0);
ecs_entity_t base_2 = ecs_new(world, Velocity);
test_assert(base_2 != 0);
test_int(ctx.invoked, 0);
ecs_entity_t e = ecs_new(world, Position);
test_assert(e != 0);
test_int(ctx.invoked, 0);
ecs_add_pair(world, e, EcsIsA, base_1);
test_int(ctx.invoked, 1); // First match, trigger
test_int(ctx.event, EcsOnAdd);
ecs_os_zeromem(&ctx);
ecs_add_pair(world, e, EcsIsA, base_2);
test_int(ctx.invoked, 0); // Second match, no trigger
ecs_add(world, e, Velocity);
test_int(ctx.invoked, 0); // Third match, no trigger
ecs_remove_pair(world, e, EcsIsA, base_2);
test_int(ctx.invoked, 0);
ecs_remove_pair(world, e, EcsIsA, base_1);
test_int(ctx.invoked, 0);
ecs_remove(world, e, Velocity);
test_int(ctx.invoked, 1); // First unmatch, trigger OnRemove
test_int(ctx.event, EcsOnRemove);
ecs_os_zeromem(&ctx);
ecs_add(world, e, Velocity);
test_int(ctx.invoked, 1); // First match, trigger
test_int(ctx.event, EcsOnAdd);
ecs_os_zeromem(&ctx);
ecs_remove(world, e, Position);
test_int(ctx.invoked, 1); // First unmatch, trigger OnRemove
test_int(ctx.event, EcsOnRemove);
ecs_fini(world);
}
void Monitor_monitor_w_wildcard(void) {
ecs_world_t *world = ecs_mini();
ECS_COMPONENT(world, Position);
ECS_TAG(world, Eats);
ECS_TAG(world, Apples);
ECS_TAG(world, Pears);
ECS_OBSERVER(world, OnPosition, EcsMonitor, Position, (Eats, *));
Probe ctx = { 0 };
ecs_set_ctx(world, &ctx, NULL);
ecs_entity_t e = ecs_new(world, Position);
test_assert(e != 0);
test_int(ctx.invoked, 0);
ecs_add_pair(world, e, Eats, Apples);
test_int(ctx.invoked, 1); // First match, trigger OnAdd
test_int(ctx.event, EcsOnAdd);
ecs_os_zeromem(&ctx);
ecs_add_pair(world, e, Eats, Pears);
test_int(ctx.invoked, 0); // Second match, no trigger
ecs_remove(world, e, Position);
test_int(ctx.invoked, 1); // First unmatch, trigger OnRemove
test_int(ctx.event, EcsOnRemove);
ecs_os_zeromem(&ctx);
ecs_add(world, e, Position);
test_int(ctx.invoked, 1); // First match, trigger OnAdd
test_int(ctx.event, EcsOnAdd);
ecs_os_zeromem(&ctx);
ecs_remove_pair(world, e, Eats, Apples);
test_int(ctx.invoked, 0);
ecs_remove_pair(world, e, Eats, Pears);
test_int(ctx.invoked, 1); // First unmatch, trigger OnRemove
test_int(ctx.event, EcsOnRemove);
ecs_fini(world);
}
static void Monitor(ecs_iter_t *it) {
probe_system_w_ctx(it, it->ctx);
}
void Monitor_monitor_at_fini(void) {
ecs_world_t *world = ecs_mini();
ECS_TAG(world, TagA);
Probe ctx = {0};
ecs_observer_init(world, &(ecs_observer_desc_t){
.filter.terms = {{ TagA }},
.events = {EcsMonitor},
.callback = Monitor,
.ctx = &ctx
});
test_int(ctx.invoked, 0);
ecs_entity_t e = ecs_new_id(world);
ecs_add(world, e, TagA);
test_int(ctx.invoked, 1);
test_int(ctx.event, EcsOnAdd);
ecs_os_zeromem(&ctx);
ecs_fini(world);
test_int(ctx.invoked, 1);
test_int(ctx.event, EcsOnRemove);
}
typedef struct {
ecs_entity_t event;
ecs_table_t *table;
ecs_table_t *other_table;
int32_t invoked;
} check_table_t;
static void CheckTable(ecs_iter_t *it) {
check_table_t *ctx = it->ctx;
test_assert(it->event == ctx->event);
test_assert(it->table == ctx->table);
test_assert(it->other_table == ctx->other_table);
ctx->invoked ++;
}
void Monitor_monitor_other_table(void) {
ecs_world_t *world = ecs_mini();
ECS_TAG(world, X);
ECS_TAG(world, Y);
ecs_entity_t x = ecs_new(world, X);
ecs_entity_t xy = ecs_new(world, X);
ecs_add(world, xy, Y);
check_table_t ctx = {0};
ecs_observer_init(world, &(ecs_observer_desc_t){
.filter.terms = {
{ X },
{ Y, .oper = EcsNot }
},
.events = {EcsMonitor},
.callback = CheckTable,
.ctx = &ctx
});
ctx.table = ecs_get_table(world, x);
ctx.other_table = NULL;
ctx.event = EcsOnAdd;
ecs_entity_t e = ecs_new(world, X);
test_int(ctx.invoked, 1);
ctx.table = ecs_get_table(world, xy);
ctx.other_table = ecs_get_table(world, x);
ctx.event = EcsOnRemove;
ecs_add(world, e, Y);
test_int(ctx.invoked, 2);
ctx.table = ecs_get_table(world, xy);
ctx.other_table = ecs_get_table(world, x);
ctx.event = EcsOnAdd;
ecs_remove(world, e, Y);
test_int(ctx.invoked, 3);
ctx.table = ecs_get_table(world, x);
ctx.other_table = NULL;
ctx.event = EcsOnRemove;
ecs_fini(world);
}
typedef struct {
ecs_entity_t event;
Position *result;
int32_t invoked;
} check_component_t;
static void CheckComponent(ecs_iter_t *it) {
check_component_t *ctx = it->ctx;
test_assert(it->event == ctx->event);
ctx->result = ecs_field(it, Position, 1);
ctx->invoked ++;
}
void Monitor_monitor_component(void) {
ecs_world_t *world = ecs_mini();
ECS_COMPONENT(world, Position);
ECS_TAG(world, Tag);
check_component_t ctx = {0};
ecs_observer_init(world, &(ecs_observer_desc_t){
.filter.terms = {
{ ecs_id(Position) },
{ Tag, .oper = EcsNot }
},
.events = {EcsMonitor},
.callback = CheckComponent,
.ctx = &ctx
});
ctx.event = EcsOnAdd;
ecs_entity_t e = ecs_new(world, Position);
const Position *expect = ecs_get(world, e, Position);
test_int(ctx.invoked, 1);
test_assert(ctx.result == expect);
ctx.event = EcsOnRemove;
ecs_add(world, e, Tag);
expect = ecs_get(world, e, Position);
test_int(ctx.invoked, 2);
test_assert(ctx.result == expect);
ctx.event = EcsOnAdd;
ecs_remove(world, e, Tag);
test_int(ctx.invoked, 3);
test_assert(ctx.result == expect);
expect = ecs_get(world, e, Position);
ctx.event = EcsOnRemove;
ecs_fini(world);
test_int(ctx.invoked, 4);
test_assert(ctx.result == expect);
}

View File

@@ -0,0 +1,483 @@
#include <api.h>
void New_setup(void) {
ecs_log_set_level(-2);
}
void New_empty(void) {
ecs_world_t *world = ecs_mini();
ecs_entity_t e = ecs_new(world, 0);
test_assert(e != 0);
test_assert(!ecs_get_type(world, e));
ecs_fini(world);
}
void New_component(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_has(world, e, Position));
ecs_fini(world);
}
void New_tag(void) {
ecs_world_t *world = ecs_mini();
ECS_ENTITY(world, Tag, 0);
ecs_entity_t e = ecs_new_w_id(world, Tag);
test_assert(e != 0);
test_assert(ecs_has_id(world, e, Tag));
ecs_fini(world);
}
void New_redefine_component(void) {
ecs_world_t *world = ecs_mini();
ecs_entity_t c = 0;
{
ECS_COMPONENT(world, Position);
c = ecs_id(Position);
}
{
ECS_COMPONENT(world, Position);
test_assert(c == ecs_id(Position));
}
ecs_fini(world);
}
void New_recycle_id_empty(void) {
ecs_world_t *world = ecs_mini();
ecs_entity_t e1 = ecs_new(world, 0);
test_assert(e1 != 0);
ecs_delete(world, e1);
ecs_entity_t e2 = ecs_new(world, 0);
test_assert(e2 != 0);
test_assert(e1 != e2);
test_assert((e1 & ECS_ENTITY_MASK) == (e2 & ECS_ENTITY_MASK));
ecs_fini(world);
}
void New_recycle_id_w_entity(void) {
ecs_world_t *world = ecs_mini();
ecs_entity_t tag = ecs_new(world, 0);
ecs_entity_t e1 = ecs_new_w_id(world, tag);
test_assert(e1 != 0);
ecs_delete(world, e1);
ecs_entity_t e2 = ecs_new_w_id(world, tag);
test_assert(e2 != 0);
test_assert(e1 != e2);
test_assert((e1 & ECS_ENTITY_MASK) == (e2 & ECS_ENTITY_MASK));
ecs_fini(world);
}
void New_recycle_empty_staged_delete(void) {
ecs_world_t *world = ecs_mini();
ecs_entity_t e1 = ecs_new(world, 0);
test_assert(e1 != 0);
ecs_defer_begin(world);
ecs_delete(world, e1);
ecs_defer_end(world);
ecs_entity_t e2 = ecs_new(world, 0);
test_assert(e2 != 0);
test_assert(e1 != e2);
test_assert((e1 & ECS_ENTITY_MASK) == (e2 & ECS_ENTITY_MASK));
ecs_fini(world);
}
void New_recycle_staged_delete(void) {
ecs_world_t *world = ecs_mini();
ECS_COMPONENT(world, Position);
ecs_entity_t e1 = ecs_new(world, Position);
test_assert(e1 != 0);
ecs_defer_begin(world);
ecs_delete(world, e1);
ecs_defer_end(world);
ecs_entity_t e2 = ecs_new(world, 0);
test_assert(e2 != 0);
test_assert(e1 != e2);
test_assert((e1 & ECS_ENTITY_MASK) == (e2 & ECS_ENTITY_MASK));
ecs_fini(world);
}
void New_new_id(void) {
ecs_world_t *world = ecs_mini();
ecs_entity_t e = ecs_new_id(world);
test_assert(e != 0);
test_assert(!ecs_get_type(world, e));
ecs_fini(world);
}
void New_new_component_id(void) {
ecs_world_t *world = ecs_mini();
ecs_entity_t e = ecs_new_low_id(world);
test_assert(e != 0);
test_assert(e < FLECS_HI_COMPONENT_ID);
test_assert(!ecs_get_type(world, e));
ecs_fini(world);
}
void New_new_component_id_skip_used(void) {
ecs_world_t *world = ecs_mini();
ECS_TAG(world, Foo);
ecs_entity_t e = ecs_new_low_id(world);
test_assert(e != 0);
test_assert(e < FLECS_HI_COMPONENT_ID);
test_assert(!ecs_get_type(world, e));
/* Explicitly set an id that is one above the last issued id */
ecs_ensure(world, e + 1);
ecs_add_id(world, e + 1, Foo);
ecs_entity_t e2 = ecs_new_low_id(world);
test_assert(e2 != 0);
test_assert(e2 < FLECS_HI_COMPONENT_ID);
test_assert(!ecs_get_type(world, e2));
test_assert(e2 != (e + 1));
ecs_fini(world);
}
void New_new_component_id_skip_to_hi_id(void) {
ecs_world_t *world = ecs_mini();
ECS_TAG(world, Foo);
ecs_entity_t e = ecs_new_low_id(world);
test_assert(e != 0);
/* Use up all low component ids */
int i;
for (i = (int)e; i < FLECS_HI_COMPONENT_ID; i ++) {
ecs_ensure(world, i);
ecs_add_id(world, i, Foo);
}
ecs_entity_t e2 = ecs_new_low_id(world);
test_assert(e2 != 0);
test_assert(e2 > FLECS_HI_COMPONENT_ID);
test_assert(!ecs_get_type(world, e2));
ecs_entity_t e3 = ecs_new_id(world);
test_assert(e3 != e2);
test_assert(e3 > e2);
test_assert(!ecs_get_type(world, e3));
ecs_fini(world);
}
void New_new_hi_component_id(void) {
ecs_world_t *world = ecs_mini();
ecs_entity_t e = ecs_new_id(world);
test_assert(e != 0);
ecs_entity_t c;
do {
c = ecs_new_low_id(world);
} while (c < FLECS_HI_COMPONENT_ID);
test_assert(c != e);
test_assert(c > e);
ecs_fini(world);
}
void New_new_w_entity_0(void) {
ecs_world_t *world = ecs_mini();
ecs_entity_t e = ecs_new_w_id(world, 0);
test_assert(e != 0);
test_assert(ecs_get_type(world, e) == NULL);
ecs_fini(world);
}
ECS_DECLARE(Foo);
void New_create_w_explicit_id_2_worlds(void) {
ecs_world_t *world_1 = ecs_mini();
ecs_world_t *world_2 = ecs_mini();
ecs_entity_t p1 = ecs_set_name(world_1, 0, "Parent");
ecs_entity_t p2 = ecs_set_name(world_2, 0, "Parent");
ecs_set_scope(world_1, p1);
ecs_set_scope(world_2, p2);
ECS_ENTITY_DEFINE(world_1, Foo, 0);
ECS_ENTITY_DEFINE(world_2, Foo, 0);
char *path = ecs_get_fullpath(world_1, Foo);
test_str(path, "Parent.Foo");
ecs_os_free(path);
path = ecs_get_fullpath(world_2, Foo);
test_str(path, "Parent.Foo");
ecs_os_free(path);
ecs_fini(world_1);
ecs_fini(world_2);
}
void New_new_w_id_0_w_with(void) {
ecs_world_t *world = ecs_mini();
ECS_TAG(world, Tag);
ecs_set_with(world, Tag);
ecs_entity_t e = ecs_new_w_id(world, 0);
test_assert(e != 0);
test_assert(ecs_has(world, e, Tag));
test_int(ecs_set_with(world, 0), Tag);
ecs_fini(world);
}
void New_new_w_id_w_with(void) {
ecs_world_t *world = ecs_mini();
ECS_TAG(world, Tag);
ECS_TAG(world, Tag2);
ecs_set_with(world, Tag);
ecs_entity_t e = ecs_new_w_id(world, Tag2);
test_assert(e != 0);
test_assert(ecs_has(world, e, Tag));
test_assert(ecs_has(world, e, Tag2));
test_int(ecs_set_with(world, 0), Tag);
ecs_fini(world);
}
void New_new_w_id_w_with_w_scope(void) {
ecs_world_t *world = ecs_mini();
ECS_TAG(world, Tag);
ECS_TAG(world, Tag2);
ecs_set_with(world, Tag);
ecs_entity_t parent = ecs_new_id(world);
ecs_set_scope(world, parent);
ecs_entity_t e = ecs_new_w_id(world, Tag2);
test_assert(e != 0);
test_assert(ecs_has(world, e, Tag));
test_assert(ecs_has(world, e, Tag2));
test_assert(ecs_has_pair(world, e, EcsChildOf, parent));
test_int(ecs_set_with(world, 0), Tag);
test_int(ecs_set_scope(world, 0), parent);
ecs_fini(world);
}
void New_new_w_id_w_with_defer(void) {
ecs_world_t *world = ecs_mini();
ECS_TAG(world, Tag);
ECS_TAG(world, Tag2);
ecs_set_with(world, Tag);
ecs_defer_begin(world);
ecs_entity_t e = ecs_new_w_id(world, Tag2);
test_assert(e != 0);
test_assert(!ecs_has(world, e, Tag));
test_assert(!ecs_has(world, e, Tag2));
ecs_defer_end(world);
test_assert(ecs_has(world, e, Tag));
test_assert(ecs_has(world, e, Tag2));
test_int(ecs_set_with(world, 0), Tag);
ecs_fini(world);
}
void New_new_w_id_w_with_defer_w_scope(void) {
ecs_world_t *world = ecs_mini();
ECS_TAG(world, Tag);
ECS_TAG(world, Tag2);
ecs_set_with(world, Tag);
ecs_entity_t parent = ecs_new_id(world);
ecs_set_scope(world, parent);
ecs_defer_begin(world);
ecs_entity_t e = ecs_new_w_id(world, Tag2);
test_assert(e != 0);
test_assert(!ecs_has(world, e, Tag));
test_assert(!ecs_has(world, e, Tag2));
test_assert(!ecs_has_pair(world, e, EcsChildOf, parent));
ecs_defer_end(world);
test_assert(ecs_has(world, e, Tag));
test_assert(ecs_has(world, e, Tag2));
test_assert(ecs_has_pair(world, e, EcsChildOf, parent));
test_int(ecs_set_with(world, 0), Tag);
test_int(ecs_set_scope(world, 0), parent);
ecs_fini(world);
}
void New_new_w_type_0_w_with(void) {
ecs_world_t *world = ecs_mini();
ECS_TAG(world, Tag);
ecs_set_with(world, Tag);
ecs_entity_t e = ecs_new(world, 0);
test_assert(e != 0);
test_assert(ecs_has(world, e, Tag));
test_int(ecs_set_with(world, 0), Tag);
ecs_fini(world);
}
void New_new_w_type_w_with(void) {
ecs_world_t *world = ecs_mini();
ECS_TAG(world, Tag);
ECS_COMPONENT(world, Position);
ecs_set_with(world, Tag);
ecs_entity_t e = ecs_new(world, Position);
test_assert(e != 0);
test_assert(ecs_has(world, e, Tag));
test_assert(ecs_has(world, e, Position));
test_int(ecs_set_with(world, 0), Tag);
ecs_fini(world);
}
void New_new_w_type_w_with_w_scope(void) {
ecs_world_t *world = ecs_mini();
ECS_TAG(world, Tag);
ECS_COMPONENT(world, Position);
ecs_set_with(world, Tag);
ecs_entity_t parent = ecs_new_id(world);
ecs_set_scope(world, parent);
ecs_entity_t e = ecs_new(world, Position);
test_assert(e != 0);
test_assert(ecs_has(world, e, Tag));
test_assert(ecs_has(world, e, Position));
test_assert(ecs_has_pair(world, e, EcsChildOf, parent));
test_int(ecs_set_with(world, 0), Tag);
test_int(ecs_set_scope(world, 0), parent);
ecs_fini(world);
}
void New_new_w_type_w_with_defer(void) {
ecs_world_t *world = ecs_mini();
ECS_TAG(world, Tag);
ECS_COMPONENT(world, Position);
ecs_set_with(world, Tag);
ecs_defer_begin(world);
ecs_entity_t e = ecs_new(world, Position);
test_assert(e != 0);
test_assert(!ecs_has(world, e, Tag));
test_assert(!ecs_has(world, e, Position));
ecs_defer_end(world);
test_assert(ecs_has(world, e, Tag));
test_assert(ecs_has(world, e, Position));
test_int(ecs_set_with(world, 0), Tag);
ecs_fini(world);
}
void New_new_w_type_w_with_defer_w_scope(void) {
ecs_world_t *world = ecs_mini();
ECS_TAG(world, Tag);
ECS_COMPONENT(world, Position);
ecs_set_with(world, Tag);
ecs_entity_t parent = ecs_new_id(world);
ecs_set_scope(world, parent);
ecs_defer_begin(world);
ecs_entity_t e = ecs_new(world, Position);
test_assert(e != 0);
test_assert(!ecs_has(world, e, Tag));
test_assert(!ecs_has(world, e, Position));
test_assert(!ecs_has_pair(world, e, EcsChildOf, parent));
ecs_defer_end(world);
test_assert(ecs_has(world, e, Tag));
test_assert(ecs_has(world, e, Position));
test_assert(ecs_has_pair(world, e, EcsChildOf, parent));
test_int(ecs_set_with(world, 0), Tag);
test_int(ecs_set_scope(world, 0), parent);
ecs_fini(world);
}

View File

@@ -0,0 +1,689 @@
#include <api.h>
void New_w_Count_empty(void) {
ecs_world_t *world = ecs_mini();
const ecs_entity_t *ids = ecs_bulk_new(world, 0, 1000);
test_assert(ids != NULL);
int i;
for (i = 0; i < 1000; i ++) {
test_assert(ids[i] != 0);
}
ecs_fini(world);
}
void New_w_Count_component(void) {
ecs_world_t *world = ecs_mini();
ECS_COMPONENT(world, Position);
const ecs_entity_t *ids = ecs_bulk_new(world, Position, 1000);
test_assert(ids != NULL);
int i;
for (i = 0; i < 1000; i ++) {
ecs_entity_t e = ids[i];
test_assert(e != 0);
test_assert(ecs_has(world, e, Position));
}
test_int(ecs_count(world, Position), 1000);
ecs_fini(world);
}
void New_w_Count_tag(void) {
ecs_world_t *world = ecs_mini();
ECS_ENTITY(world, Tag, 0);
const ecs_entity_t *ids = ecs_bulk_new_w_id(world, Tag, 1000);
test_assert(ids != NULL);
test_int(ecs_count_id(world, Tag), 1000);
int i;
for (i = 0; i < 1000; i ++) {
ecs_entity_t e = ids[i];
test_assert(e != 0);
test_assert(ecs_has_id(world, e, Tag));
}
ecs_fini(world);
}
void New_w_Count_bulk_init_empty(void) {
ecs_world_t *world = ecs_mini();
const ecs_entity_t *entities = ecs_bulk_init(world, &(ecs_bulk_desc_t){
.count = 3
});
test_assert(entities != NULL);
test_assert(entities[0] != 0);
test_assert(entities[1] != 0);
test_assert(entities[2] != 0);
test_assert(entities[0] != entities[1]);
test_assert(entities[0] != entities[2]);
test_assert(entities[0] != entities[1]);
test_assert(entities[1] != entities[2]);
test_assert(ecs_is_alive(world, entities[0]));
test_assert(ecs_is_alive(world, entities[1]));
test_assert(ecs_is_alive(world, entities[2]));
ecs_fini(world);
}
void New_w_Count_bulk_init_empty_w_entities(void) {
ecs_world_t *world = ecs_mini();
ecs_entity_t ents[] = {1000, 1001, 1002};
const ecs_entity_t *entities = ecs_bulk_init(world, &(ecs_bulk_desc_t){
.entities = ents,
.count = 3
});
test_assert(entities != NULL);
test_assert(entities[0] != 0);
test_assert(entities[1] != 0);
test_assert(entities[2] != 0);
test_uint(entities[0], 1000);
test_uint(entities[1], 1001);
test_uint(entities[2], 1002);
test_assert(ecs_is_alive(world, entities[0]));
test_assert(ecs_is_alive(world, entities[1]));
test_assert(ecs_is_alive(world, entities[2]));
ecs_fini(world);
}
void New_w_Count_bulk_init_1_tag(void) {
ecs_world_t *world = ecs_mini();
ECS_TAG(world, Tag);
const ecs_entity_t *entities = ecs_bulk_init(world, &(ecs_bulk_desc_t){
.count = 3,
.ids = {Tag}
});
test_assert(entities != NULL);
test_assert(entities[0] != 0);
test_assert(entities[1] != 0);
test_assert(entities[2] != 0);
test_assert(entities[0] != entities[1]);
test_assert(entities[0] != entities[2]);
test_assert(entities[0] != entities[1]);
test_assert(entities[1] != entities[2]);
test_assert(ecs_is_alive(world, entities[0]));
test_assert(ecs_is_alive(world, entities[1]));
test_assert(ecs_is_alive(world, entities[2]));
test_assert(ecs_has(world, entities[0], Tag));
test_assert(ecs_has(world, entities[1], Tag));
test_assert(ecs_has(world, entities[2], Tag));
ecs_fini(world);
}
void New_w_Count_bulk_init_1_tag_w_entities(void) {
ecs_world_t *world = ecs_mini();
ECS_TAG(world, Tag);
ecs_entity_t ents[] = {1000, 1001, 1002};
const ecs_entity_t *entities = ecs_bulk_init(world, &(ecs_bulk_desc_t){
.entities = ents,
.count = 3,
.ids = {Tag}
});
test_assert(entities != NULL);
test_assert(entities[0] != 0);
test_assert(entities[1] != 0);
test_assert(entities[2] != 0);
test_uint(entities[0], 1000);
test_uint(entities[1], 1001);
test_uint(entities[2], 1002);
test_assert(ecs_is_alive(world, entities[0]));
test_assert(ecs_is_alive(world, entities[1]));
test_assert(ecs_is_alive(world, entities[2]));
test_assert(ecs_has(world, entities[0], Tag));
test_assert(ecs_has(world, entities[1], Tag));
test_assert(ecs_has(world, entities[2], Tag));
ecs_fini(world);
}
void New_w_Count_bulk_init_2_tags(void) {
ecs_world_t *world = ecs_mini();
ECS_TAG(world, TagA);
ECS_TAG(world, TagB);
const ecs_entity_t *entities = ecs_bulk_init(world, &(ecs_bulk_desc_t){
.count = 3,
.ids = {TagA, TagB}
});
test_assert(entities != NULL);
test_assert(entities[0] != 0);
test_assert(entities[1] != 0);
test_assert(entities[2] != 0);
test_assert(entities[0] != entities[1]);
test_assert(entities[0] != entities[2]);
test_assert(entities[0] != entities[1]);
test_assert(entities[1] != entities[2]);
test_assert(ecs_is_alive(world, entities[0]));
test_assert(ecs_is_alive(world, entities[1]));
test_assert(ecs_is_alive(world, entities[2]));
test_assert(ecs_has(world, entities[0], TagA));
test_assert(ecs_has(world, entities[1], TagA));
test_assert(ecs_has(world, entities[2], TagA));
test_assert(ecs_has(world, entities[0], TagB));
test_assert(ecs_has(world, entities[1], TagB));
test_assert(ecs_has(world, entities[2], TagB));
ecs_fini(world);
}
void New_w_Count_bulk_init_1_component(void) {
ecs_world_t *world = ecs_mini();
ECS_COMPONENT(world, Position);
const ecs_entity_t *entities = ecs_bulk_init(world, &(ecs_bulk_desc_t){
.count = 3,
.ids = {ecs_id(Position)}
});
test_assert(entities != NULL);
test_assert(entities[0] != 0);
test_assert(entities[1] != 0);
test_assert(entities[2] != 0);
test_assert(entities[0] != entities[1]);
test_assert(entities[0] != entities[2]);
test_assert(entities[0] != entities[1]);
test_assert(entities[1] != entities[2]);
test_assert(ecs_is_alive(world, entities[0]));
test_assert(ecs_is_alive(world, entities[1]));
test_assert(ecs_is_alive(world, entities[2]));
test_assert(ecs_has(world, entities[0], Position));
test_assert(ecs_has(world, entities[1], Position));
test_assert(ecs_has(world, entities[2], Position));
test_assert( ecs_get(world, entities[0], Position) != NULL);
test_assert( ecs_get(world, entities[1], Position) != NULL);
test_assert( ecs_get(world, entities[2], Position) != NULL);
ecs_fini(world);
}
void New_w_Count_bulk_init_2_components(void) {
ecs_world_t *world = ecs_mini();
ECS_COMPONENT(world, Position);
ECS_COMPONENT(world, Velocity);
const ecs_entity_t *entities = ecs_bulk_init(world, &(ecs_bulk_desc_t){
.count = 3,
.ids = {ecs_id(Position), ecs_id(Velocity)}
});
test_assert(entities != NULL);
test_assert(entities[0] != 0);
test_assert(entities[1] != 0);
test_assert(entities[2] != 0);
test_assert(entities[0] != entities[1]);
test_assert(entities[0] != entities[2]);
test_assert(entities[0] != entities[1]);
test_assert(entities[1] != entities[2]);
test_assert(ecs_is_alive(world, entities[0]));
test_assert(ecs_is_alive(world, entities[1]));
test_assert(ecs_is_alive(world, entities[2]));
test_assert(ecs_has(world, entities[0], Position));
test_assert(ecs_has(world, entities[1], Position));
test_assert(ecs_has(world, entities[2], Position));
test_assert(ecs_has(world, entities[0], Velocity));
test_assert(ecs_has(world, entities[1], Velocity));
test_assert(ecs_has(world, entities[2], Velocity));
test_assert( ecs_get(world, entities[0], Position) != NULL);
test_assert( ecs_get(world, entities[1], Position) != NULL);
test_assert( ecs_get(world, entities[2], Position) != NULL);
test_assert( ecs_get(world, entities[0], Velocity) != NULL);
test_assert( ecs_get(world, entities[1], Velocity) != NULL);
test_assert( ecs_get(world, entities[2], Velocity) != NULL);
ecs_fini(world);
}
void New_w_Count_bulk_init_1_component_w_value(void) {
ecs_world_t *world = ecs_mini();
ECS_COMPONENT(world, Position);
Position p[] = {
{10, 20},
{30, 40},
{50, 60}
};
void *data[] = {p};
const ecs_entity_t *entities = ecs_bulk_init(world, &(ecs_bulk_desc_t){
.count = 3,
.ids = {ecs_id(Position)},
.data = data
});
test_assert(entities != NULL);
test_assert(entities[0] != 0);
test_assert(entities[1] != 0);
test_assert(entities[2] != 0);
test_assert(entities[0] != entities[1]);
test_assert(entities[0] != entities[2]);
test_assert(entities[0] != entities[1]);
test_assert(entities[1] != entities[2]);
test_assert(ecs_is_alive(world, entities[0]));
test_assert(ecs_is_alive(world, entities[1]));
test_assert(ecs_is_alive(world, entities[2]));
test_assert(ecs_has(world, entities[0], Position));
test_assert(ecs_has(world, entities[1], Position));
test_assert(ecs_has(world, entities[2], Position));
const Position *ptr;
ptr = ecs_get(world, entities[0], Position);
test_assert(ptr != NULL);
test_int(ptr->x, 10);
test_int(ptr->y, 20);
ptr = ecs_get(world, entities[1], Position);
test_assert(ptr != NULL);
test_int(ptr->x, 30);
test_int(ptr->y, 40);
ptr = ecs_get(world, entities[2], Position);
test_assert(ptr != NULL);
test_int(ptr->x, 50);
test_int(ptr->y, 60);
ecs_fini(world);
}
void New_w_Count_bulk_init_2_components_w_value(void) {
ecs_world_t *world = ecs_mini();
ECS_COMPONENT(world, Position);
ECS_COMPONENT(world, Velocity);
Position p[] = {
{10, 20},
{30, 40},
{50, 60}
};
Velocity v[] = {
{1, 2},
{3, 4},
{5, 6}
};
void *data[] = {p, v};
const ecs_entity_t *entities = ecs_bulk_init(world, &(ecs_bulk_desc_t){
.count = 3,
.ids = {ecs_id(Position), ecs_id(Velocity)},
.data = data
});
test_assert(entities != NULL);
test_assert(entities[0] != 0);
test_assert(entities[1] != 0);
test_assert(entities[2] != 0);
test_assert(entities[0] != entities[1]);
test_assert(entities[0] != entities[2]);
test_assert(entities[0] != entities[1]);
test_assert(entities[1] != entities[2]);
test_assert(ecs_is_alive(world, entities[0]));
test_assert(ecs_is_alive(world, entities[1]));
test_assert(ecs_is_alive(world, entities[2]));
test_assert(ecs_has(world, entities[0], Position));
test_assert(ecs_has(world, entities[1], Position));
test_assert(ecs_has(world, entities[2], Position));
test_assert(ecs_has(world, entities[0], Velocity));
test_assert(ecs_has(world, entities[1], Velocity));
test_assert(ecs_has(world, entities[2], Velocity));
{
const Position *ptr;
ptr = ecs_get(world, entities[0], Position);
test_assert(ptr != NULL);
test_int(ptr->x, 10);
test_int(ptr->y, 20);
ptr = ecs_get(world, entities[1], Position);
test_assert(ptr != NULL);
test_int(ptr->x, 30);
test_int(ptr->y, 40);
ptr = ecs_get(world, entities[2], Position);
test_assert(ptr != NULL);
test_int(ptr->x, 50);
test_int(ptr->y, 60);
}
{
const Velocity *ptr;
ptr = ecs_get(world, entities[0], Velocity);
test_assert(ptr != NULL);
test_int(ptr->x, 1);
test_int(ptr->y, 2);
ptr = ecs_get(world, entities[1], Velocity);
test_assert(ptr != NULL);
test_int(ptr->x, 3);
test_int(ptr->y, 4);
ptr = ecs_get(world, entities[2], Velocity);
test_assert(ptr != NULL);
test_int(ptr->x, 5);
test_int(ptr->y, 6);
}
ecs_fini(world);
}
void New_w_Count_bulk_init_2_components_tag_w_value(void) {
ecs_world_t *world = ecs_mini();
ECS_TAG(world, Tag);
ECS_COMPONENT(world, Position);
ECS_COMPONENT(world, Velocity);
Position p[] = {
{10, 20},
{30, 40},
{50, 60}
};
Velocity v[] = {
{1, 2},
{3, 4},
{5, 6}
};
void *data[] = {p, NULL, v};
const ecs_entity_t *entities = ecs_bulk_init(world, &(ecs_bulk_desc_t){
.count = 3,
.ids = {ecs_id(Position), Tag, ecs_id(Velocity)},
.data = data
});
test_assert(entities != NULL);
test_assert(entities[0] != 0);
test_assert(entities[1] != 0);
test_assert(entities[2] != 0);
test_assert(entities[0] != entities[1]);
test_assert(entities[0] != entities[2]);
test_assert(entities[0] != entities[1]);
test_assert(entities[1] != entities[2]);
test_assert(ecs_is_alive(world, entities[0]));
test_assert(ecs_is_alive(world, entities[1]));
test_assert(ecs_is_alive(world, entities[2]));
test_assert(ecs_has(world, entities[0], Tag));
test_assert(ecs_has(world, entities[1], Tag));
test_assert(ecs_has(world, entities[2], Tag));
test_assert(ecs_has(world, entities[0], Position));
test_assert(ecs_has(world, entities[1], Position));
test_assert(ecs_has(world, entities[2], Position));
test_assert(ecs_has(world, entities[0], Velocity));
test_assert(ecs_has(world, entities[1], Velocity));
test_assert(ecs_has(world, entities[2], Velocity));
{
const Position *ptr;
ptr = ecs_get(world, entities[0], Position);
test_assert(ptr != NULL);
test_int(ptr->x, 10);
test_int(ptr->y, 20);
ptr = ecs_get(world, entities[1], Position);
test_assert(ptr != NULL);
test_int(ptr->x, 30);
test_int(ptr->y, 40);
ptr = ecs_get(world, entities[2], Position);
test_assert(ptr != NULL);
test_int(ptr->x, 50);
test_int(ptr->y, 60);
}
{
const Velocity *ptr;
ptr = ecs_get(world, entities[0], Velocity);
test_assert(ptr != NULL);
test_int(ptr->x, 1);
test_int(ptr->y, 2);
ptr = ecs_get(world, entities[1], Velocity);
test_assert(ptr != NULL);
test_int(ptr->x, 3);
test_int(ptr->y, 4);
ptr = ecs_get(world, entities[2], Velocity);
test_assert(ptr != NULL);
test_int(ptr->x, 5);
test_int(ptr->y, 6);
}
ecs_fini(world);
}
void New_w_Count_add_after_bulk(void) {
ecs_world_t *world = ecs_mini();
ECS_ENTITY(world, Tag, 0);
const ecs_entity_t *ids = ecs_bulk_new_w_id(world, Tag, 10);
test_assert(ids != NULL);
test_int(ecs_count_id(world, Tag), 10);
int i;
for (i = 0; i < 10; i ++) {
ecs_entity_t e = ids[i];
test_assert(e != 0);
test_assert(ecs_has_id(world, e, Tag));
}
ecs_entity_t e = ecs_new_id(world);
ecs_add(world, e, Tag);
test_assert(ecs_has(world, e, Tag));
ecs_fini(world);
}
void New_w_Count_add_after_bulk_w_component(void) {
ecs_world_t *world = ecs_mini();
ECS_COMPONENT(world, Position);
const ecs_entity_t *ids = ecs_bulk_new(world, Position, 10);
test_assert(ids != NULL);
test_int(ecs_count(world, Position), 10);
int i;
for (i = 0; i < 10; i ++) {
ecs_entity_t e = ids[i];
test_assert(e != 0);
test_assert(ecs_has(world, e, Position));
}
ecs_entity_t e = ecs_new_id(world);
ecs_add(world, e, Position);
test_assert(ecs_has(world, e, Position));
ecs_fini(world);
}
void New_w_Count_add_after_bulk_w_ctor(void) {
ecs_world_t *world = ecs_mini();
ECS_COMPONENT(world, Position);
ecs_set_hooks(world, Position, {
.ctor = ecs_default_ctor
});
const ecs_entity_t *ids = ecs_bulk_new(world, Position, 10);
test_assert(ids != NULL);
test_int(ecs_count(world, Position), 10);
int i;
for (i = 0; i < 10; i ++) {
ecs_entity_t e = ids[i];
test_assert(e != 0);
test_assert(ecs_has(world, e, Position));
}
ecs_entity_t e = ecs_new_id(world);
ecs_add(world, e, Position);
test_assert(ecs_has(world, e, Position));
ecs_fini(world);
}
void New_w_Count_recycle_1_of_2(void) {
ecs_world_t *world = ecs_init();
ecs_entity_t tag = ecs_new_id(world);
/* ecs_entity_t e0 = */ ecs_new_id(world);
ecs_entity_t e1 = ecs_new_id(world);
ecs_delete(world, e1);
const ecs_entity_t *ids = ecs_bulk_new_w_id(world, tag, 2);
test_assert(ids[0] != 0);
test_assert(ids[1] != 0);
test_assert(ids[0] != e1);
test_assert((uint32_t)ids[0] == e1);
ecs_fini(world);
}
void New_w_Count_recycle_1_of_3(void) {
ecs_world_t *world = ecs_init();
ecs_entity_t tag = ecs_new_id(world);
/* ecs_entity_t e0 = */ ecs_new_id(world);
ecs_entity_t e1 = ecs_new_id(world);
ecs_delete(world, e1);
const ecs_entity_t *ids = ecs_bulk_new_w_id(world, tag, 3);
test_assert(ids[0] != 0);
test_assert(ids[1] != 0);
test_assert(ids[2] != 0);
test_assert(ids[0] != e1);
test_assert((uint32_t)ids[0] == e1);
ecs_fini(world);
}
void New_w_Count_recycle_2_of_3(void) {
ecs_world_t *world = ecs_init();
ecs_entity_t tag = ecs_new_id(world);
ecs_entity_t e0 = ecs_new_id(world);
ecs_entity_t e1 = ecs_new_id(world);
ecs_delete(world, e1);
ecs_delete(world, e0);
const ecs_entity_t *ids = ecs_bulk_new_w_id(world, tag, 3);
test_assert(ids[0] != 0);
test_assert(ids[1] != 0);
test_assert(ids[2] != 0);
test_assert(ids[0] != e0);
test_assert(ids[1] != e1);
test_assert((uint32_t)ids[0] == e0);
test_assert((uint32_t)ids[1] == e1);
ecs_fini(world);
}
void New_w_Count_bulk_init_w_table(void) {
ecs_world_t *world = ecs_init();
ECS_TAG(world, Tag);
ecs_table_t *table = ecs_table_add_id(world, NULL, Tag);
ecs_bulk_desc_t desc = {0};
desc.count = 3;
desc.table = table;
const ecs_entity_t *entities = ecs_bulk_init(world, &desc);
test_assert(entities != NULL);
test_assert(ecs_has(world, entities[0], Tag));
test_assert(ecs_has(world, entities[1], Tag));
test_assert(ecs_has(world, entities[2], Tag));
test_assert(ecs_get_table(world, entities[0]) == table);
test_assert(ecs_get_table(world, entities[1]) == table);
test_assert(ecs_get_table(world, entities[2]) == table);
test_int(3, ecs_count(world, Tag));
ecs_delete_with(world, Tag);
test_int(0, ecs_count(world, Tag));
ecs_fini(world);
}

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,777 @@
#include <api.h>
static
void OnPosition(ecs_iter_t *it) {
probe_iter(it);
}
static
void Add_to_current(ecs_iter_t *it) {
IterData *ctx = ecs_get_ctx(it->world);
int i;
for (i = 0; i < it->count; i ++) {
if (ctx->component) {
ecs_add_id(it->world, it->entities[i], ctx->component);
test_assert( !!ecs_get_type(it->world, it->entities[i]));
}
if (ctx->component_2) {
ecs_add_id(it->world, it->entities[i], ctx->component_2);
}
ctx->entity_count ++;
}
}
static
void Remove_from_current(ecs_iter_t *it) {
IterData *ctx = ecs_get_ctx(it->world);
int i;
for (i = 0; i < it->count; i ++) {
ecs_entity_t e = it->entities[i];
if (ctx->component) {
ecs_remove_id(it->world, e, ctx->component);
}
if (ctx->component_2) {
ecs_remove_id(it->world, e, ctx->component_2);
}
ctx->entity_count ++;
}
}
static Probe pv_probe;
static
void On_PV(ecs_iter_t *it) {
Position *p = ecs_field(it, Position, 1);
Velocity *v = ecs_field(it, Velocity, 2);
probe_system_w_ctx(it, &pv_probe);
int i;
for (i = 0; i < it->count; i ++) {
p[i].x += v[i].x;
p[i].y += v[i].y;
}
}
void ObserverOnSet_set_1_of_1(void) {
ecs_world_t *world = ecs_mini();
ECS_COMPONENT(world, Position);
ECS_COMPONENT(world, Velocity);
ECS_OBSERVER(world, OnPosition, EcsOnSet, Position);
Probe ctx = { 0 };
ecs_set_ctx(world, &ctx, NULL);
ecs_entity_t e = ecs_new(world, Position);
test_int(ctx.invoked, 0);
ecs_set(world, e, Position, {10, 20});
test_int(ctx.invoked, 1);
test_int(ctx.count, 1);
test_int(ctx.system, OnPosition);
test_int(ctx.term_count, 1);
test_null(ctx.param);
test_int(ctx.e[0], e);
test_int(ctx.c[0][0], ecs_id(Position));
test_int(ctx.s[0][0], 0);
ecs_os_zeromem(&ctx);
ecs_add(world, e, Velocity);
test_int(ctx.invoked, 0);
ecs_set(world, e, Velocity, {10, 20});
test_int(ctx.invoked, 0);
ecs_set(world, e, Position, {10, 20});
test_int(ctx.invoked, 1);
test_int(ctx.count, 1);
test_int(ctx.system, OnPosition);
test_int(ctx.term_count, 1);
test_null(ctx.param);
test_int(ctx.e[0], e);
test_int(ctx.c[0][0], ecs_id(Position));
test_int(ctx.s[0][0], 0);
ecs_fini(world);
}
void ObserverOnSet_set_1_of_2(void) {
ecs_world_t *world = ecs_mini();
ECS_COMPONENT(world, Position);
ECS_COMPONENT(world, Velocity);
ECS_OBSERVER(world, OnPosition, EcsOnSet, Position, Velocity);
Probe ctx = { 0 };
ecs_set_ctx(world, &ctx, NULL);
ecs_entity_t e = ecs_new(world, Position);
test_int(ctx.invoked, 0);
ecs_set(world, e, Position, {10, 20});
test_int(ctx.invoked, 0);
ecs_add(world, e, Velocity);
test_int(ctx.invoked, 0);
ecs_set(world, e, Velocity, {10, 20});
test_int(ctx.invoked, 1);
test_int(ctx.count, 1);
test_int(ctx.system, OnPosition);
test_int(ctx.term_count, 2);
test_null(ctx.param);
test_int(ctx.e[0], e);
test_int(ctx.c[0][0], ecs_id(Position));
test_int(ctx.s[0][0], 0);
test_int(ctx.c[0][1], ecs_id(Velocity));
test_int(ctx.s[0][1], 0);
ecs_os_zeromem(&ctx);
ecs_set(world, e, Position, {10, 20});
test_int(ctx.invoked, 1);
test_int(ctx.count, 1);
test_int(ctx.system, OnPosition);
test_int(ctx.term_count, 2);
test_null(ctx.param);
test_int(ctx.e[0], e);
test_int(ctx.c[0][0], ecs_id(Position));
test_int(ctx.s[0][0], 0);
test_int(ctx.c[0][1], ecs_id(Velocity));
test_int(ctx.s[0][1], 0);
ecs_fini(world);
}
void ObserverOnSet_set_1_of_3(void) {
ecs_world_t *world = ecs_mini();
ECS_COMPONENT(world, Position);
ECS_COMPONENT(world, Velocity);
ECS_COMPONENT(world, Mass);
ECS_OBSERVER(world, OnPosition, EcsOnSet, Position, Velocity, Mass);
Probe ctx = { 0 };
ecs_set_ctx(world, &ctx, NULL);
ecs_entity_t e = ecs_new(world, Position);
test_int(ctx.invoked, 0);
ecs_set(world, e, Position, {10, 20});
test_int(ctx.invoked, 0);
ecs_add(world, e, Velocity);
test_int(ctx.invoked, 0);
ecs_add(world, e, Mass);
test_int(ctx.invoked, 0);
ecs_set(world, e, Velocity, {10, 20});
test_int(ctx.invoked, 1);
test_int(ctx.count, 1);
test_int(ctx.system, OnPosition);
test_int(ctx.term_count, 3);
test_null(ctx.param);
test_int(ctx.e[0], e);
test_int(ctx.c[0][0], ecs_id(Position));
test_int(ctx.s[0][0], 0);
test_int(ctx.c[0][1], ecs_id(Velocity));
test_int(ctx.s[0][1], 0);
test_int(ctx.c[0][2], ecs_id(Mass));
test_int(ctx.s[0][2], 0);
ecs_os_zeromem(&ctx);
ecs_set(world, e, Position, {10, 20});
test_int(ctx.invoked, 1);
test_int(ctx.count, 1);
test_int(ctx.system, OnPosition);
test_int(ctx.term_count, 3);
test_null(ctx.param);
test_int(ctx.e[0], e);
test_int(ctx.c[0][0], ecs_id(Position));
test_int(ctx.s[0][0], 0);
test_int(ctx.c[0][1], ecs_id(Velocity));
test_int(ctx.s[0][1], 0);
test_int(ctx.c[0][2], ecs_id(Mass));
test_int(ctx.s[0][2], 0);
ecs_os_zeromem(&ctx);
ecs_set(world, e, Mass, {10});
test_int(ctx.invoked, 1);
test_int(ctx.count, 1);
test_int(ctx.system, OnPosition);
test_int(ctx.term_count, 3);
test_null(ctx.param);
test_int(ctx.e[0], e);
test_int(ctx.c[0][0], ecs_id(Position));
test_int(ctx.s[0][0], 0);
test_int(ctx.c[0][1], ecs_id(Velocity));
test_int(ctx.s[0][1], 0);
test_int(ctx.c[0][2], ecs_id(Mass));
test_int(ctx.s[0][2], 0);
ecs_fini(world);
}
void ObserverOnSet_set_1_of_2_1_from_base(void) {
ecs_world_t *world = ecs_mini();
ECS_COMPONENT(world, Position);
ECS_COMPONENT(world, Velocity);
ECS_ENTITY(world, Base, Position);
ECS_OBSERVER(world, OnPosition, EcsOnSet, Position(self|up), Velocity);
Probe ctx = { 0 };
ecs_set_ctx(world, &ctx, NULL);
ecs_entity_t e = ecs_new_w_pair(world, EcsIsA, Base);
test_int(ctx.invoked, 0);
ecs_add(world, e, Velocity);
test_int(ctx.invoked, 0);
ecs_set(world, e, Velocity, {10, 20});
test_int(ctx.invoked, 1);
test_int(ctx.count, 1);
test_int(ctx.system, OnPosition);
test_int(ctx.term_count, 2);
test_null(ctx.param);
test_int(ctx.e[0], e);
test_int(ctx.c[0][0], ecs_id(Position));
test_int(ctx.s[0][0], Base);
test_int(ctx.c[0][1], ecs_id(Velocity));
test_int(ctx.s[0][1], 0);
ecs_fini(world);
}
void ObserverOnSet_set_1_of_3_1_from_base(void) {
ecs_world_t *world = ecs_mini();
ECS_COMPONENT(world, Position);
ECS_COMPONENT(world, Velocity);
ECS_COMPONENT(world, Mass);
ECS_ENTITY(world, Base, Position);
ECS_OBSERVER(world, OnPosition, EcsOnSet, Position(self|up), Velocity, Mass);
Probe ctx = { 0 };
ecs_set_ctx(world, &ctx, NULL);
ecs_entity_t e = ecs_new_w_pair(world, EcsIsA, Base);
test_int(ctx.invoked, 0);
ecs_add(world, e, Velocity);
test_int(ctx.invoked, 0);
ecs_add(world, e, Mass);
test_int(ctx.invoked, 0);
ecs_set(world, e, Velocity, {10, 20});
test_int(ctx.invoked, 1);
test_int(ctx.count, 1);
test_int(ctx.system, OnPosition);
test_int(ctx.term_count, 3);
test_null(ctx.param);
test_int(ctx.e[0], e);
test_int(ctx.c[0][0], ecs_id(Position));
test_int(ctx.s[0][0], Base);
test_int(ctx.c[0][1], ecs_id(Velocity));
test_int(ctx.s[0][1], 0);
test_int(ctx.c[0][2], ecs_id(Mass));
test_int(ctx.s[0][2], 0);
ecs_os_zeromem(&ctx);
ecs_set(world, e, Mass, {10});
test_int(ctx.invoked, 1);
test_int(ctx.count, 1);
test_int(ctx.system, OnPosition);
test_int(ctx.term_count, 3);
test_null(ctx.param);
test_int(ctx.e[0], e);
test_int(ctx.c[0][0], ecs_id(Position));
test_int(ctx.s[0][0], Base);
test_int(ctx.c[0][1], ecs_id(Velocity));
test_int(ctx.s[0][1], 0);
test_int(ctx.c[0][2], ecs_id(Mass));
test_int(ctx.s[0][2], 0);
ecs_fini(world);
}
void ObserverOnSet_add_base(void) {
ecs_world_t *world = ecs_mini();
ECS_COMPONENT(world, Position);
ECS_COMPONENT(world, Velocity);
ECS_ENTITY(world, Base, Position);
ECS_OBSERVER(world, OnPosition, EcsOnSet, Position(self|up), Velocity);
Probe ctx = { 0 };
ecs_set_ctx(world, &ctx, NULL);
ecs_entity_t e = ecs_new(world, Velocity);
test_int(ctx.invoked, 0);
ecs_add_pair(world, e, EcsIsA, Base);
test_int(ctx.invoked, 1);
test_int(ctx.count, 1);
test_int(ctx.system, OnPosition);
test_int(ctx.term_count, 2);
test_null(ctx.param);
test_int(ctx.e[0], e);
test_int(ctx.c[0][0], ecs_id(Position));
test_int(ctx.s[0][0], Base);
test_int(ctx.c[0][1], ecs_id(Velocity));
test_int(ctx.s[0][1], 0);
ecs_fini(world);
}
void ObserverOnSet_add_base_to_1_overridden(void) {
ecs_world_t *world = ecs_mini();
ECS_COMPONENT(world, Position);
ECS_ENTITY(world, Base, Position);
ECS_OBSERVER(world, OnPosition, EcsOnSet, Position(self|up));
Probe ctx = { 0 };
ecs_set_ctx(world, &ctx, NULL);
ecs_entity_t e = ecs_new(world, Position);
test_int(ctx.invoked, 0);
ecs_add_pair(world, e, EcsIsA, Base);
test_int(ctx.invoked, 0);
ecs_fini(world);
}
void ObserverOnSet_add_base_to_2_overridden(void) {
ecs_world_t *world = ecs_mini();
ECS_COMPONENT(world, Position);
ECS_COMPONENT(world, Velocity);
ECS_ENTITY(world, Base, Position, Velocity);
ECS_OBSERVER(world, OnPosition, EcsOnSet, Position(self|up), Velocity(self|up));
Probe ctx = { 0 };
ecs_set_ctx(world, &ctx, NULL);
ecs_entity_t e = ecs_new(world, Position);
ecs_add(world, e, Velocity);
test_int(ctx.invoked, 0);
ecs_add_pair(world, e, EcsIsA, Base);
test_int(ctx.invoked, 0);
ecs_fini(world);
}
void ObserverOnSet_add_base_to_1_of_2_overridden(void) {
ecs_world_t *world = ecs_mini();
ECS_COMPONENT(world, Position);
ECS_COMPONENT(world, Velocity);
ECS_ENTITY(world, Base, Position, Velocity);
ECS_OBSERVER(world, OnPosition, EcsOnSet, Position(self|up));
Probe ctx = { 0 };
ecs_set_ctx(world, &ctx, NULL);
ecs_entity_t e = ecs_new(world, Velocity);
test_int(ctx.invoked, 0);
ecs_add_pair(world, e, EcsIsA, Base);
test_int(ctx.invoked, 1);
test_int(ctx.count, 1);
test_int(ctx.system, OnPosition);
test_int(ctx.term_count, 1);
test_null(ctx.param);
test_int(ctx.e[0], e);
test_int(ctx.c[0][0], ecs_id(Position));
test_int(ctx.s[0][0], Base);
ecs_os_zeromem(&ctx);
e = ecs_new(world, Position);
test_int(ctx.invoked, 0);
ecs_add_pair(world, e, EcsIsA, Base);
test_int(ctx.invoked, 0);
ecs_fini(world);
}
void ObserverOnSet_on_set_after_remove_override(void) {
ecs_world_t *world = ecs_mini();
ECS_COMPONENT(world, Position);
ECS_COMPONENT(world, Velocity);
ECS_ENTITY(world, Base, Position);
ECS_OBSERVER(world, OnPosition, EcsOnSet, Position);
Probe ctx = { 0 };
ecs_set_ctx(world, &ctx, NULL);
ecs_entity_t e = ecs_new(world, Position);
test_int(ctx.invoked, 0);
ecs_add_pair(world, e, EcsIsA, Base);
test_int(ctx.invoked, 0);
ecs_remove(world, e, Position);
test_int(ctx.invoked, 1);
test_int(ctx.count, 1);
test_int(ctx.system, OnPosition);
test_int(ctx.term_count, 1);
test_null(ctx.param);
test_int(ctx.e[0], e);
test_int(ctx.c[0][0], ecs_id(Position));
test_int(ctx.s[0][0], Base);
ecs_fini(world);
}
void ObserverOnSet_no_set_after_remove_base(void) {
ecs_world_t *world = ecs_mini();
ECS_COMPONENT(world, Position);
ECS_COMPONENT(world, Velocity);
ECS_ENTITY(world, Base, Position);
ECS_OBSERVER(world, OnPosition, EcsOnSet, Position(self|up));
Probe ctx = { 0 };
ecs_set_ctx(world, &ctx, NULL);
ecs_entity_t e = ecs_new(world, Position);
test_int(ctx.invoked, 0);
ecs_add_pair(world, e, EcsIsA, Base);
test_int(ctx.invoked, 0);
ecs_remove_id(world, e, ecs_pair(EcsIsA, Base));
test_int(ctx.invoked, 0);
ecs_fini(world);
}
void ObserverOnSet_un_set_after_remove(void) {
ecs_world_t *world = ecs_mini();
ECS_COMPONENT(world, Position);
ECS_OBSERVER(world, OnPosition, EcsUnSet, Position);
Probe ctx = { 0 };
ecs_set_ctx(world, &ctx, NULL);
ecs_entity_t e = ecs_new(world, Position);
test_int(ctx.invoked, 0);
ecs_remove(world, e, Position);
test_int(ctx.invoked, 1);
ecs_fini(world);
}
void ObserverOnSet_un_set_after_remove_base(void) {
ecs_world_t *world = ecs_mini();
ECS_COMPONENT(world, Position);
ECS_ENTITY(world, Base, Position);
ECS_OBSERVER(world, OnPosition, EcsUnSet, Position(self|up));
Probe ctx = { 0 };
ecs_set_ctx(world, &ctx, NULL);
ecs_entity_t e = ecs_new(world, 0);
test_int(ctx.invoked, 0);
ecs_add_pair(world, e, EcsIsA, Base);
test_int(ctx.invoked, 0);
ecs_remove_id(world, e, ecs_pair(EcsIsA, Base));
test_int(ctx.invoked, 1);
ecs_fini(world);
}
void ObserverOnSet_add_to_current_in_on_set(void) {
ecs_world_t *world = ecs_mini();
ECS_COMPONENT(world, Position);
ECS_COMPONENT(world, Velocity);
ECS_OBSERVER(world, Add_to_current, EcsOnSet, Position);
IterData ctx = {.component = ecs_id(Velocity)};
ecs_set_ctx(world, &ctx, NULL);
/* Create entities from scratch so they don't have the EcsName component */
ecs_entity_t e1 = ecs_set(world, 0, Position, {10, 20});
ecs_entity_t e2 = ecs_set(world, 0, Position, {11, 21});
ecs_entity_t e3 = ecs_set(world, 0, Position, {12, 22});
test_assert( ecs_has(world, e1, Position));
test_assert( ecs_has(world, e2, Position));
test_assert( ecs_has(world, e3, Position));
test_assert( ecs_has(world, e1, Velocity));
test_assert( ecs_has(world, e2, Velocity));
test_assert( ecs_has(world, e3, Velocity));
const Position *p = ecs_get(world, e1, Position);
test_int(p->x, 10);
test_int(p->y, 20);
p = ecs_get(world, e2, Position);
test_int(p->x, 11);
test_int(p->y, 21);
p = ecs_get(world, e3, Position);
test_int(p->x, 12);
test_int(p->y, 22);
ecs_fini(world);
}
void ObserverOnSet_remove_from_current_in_on_set(void) {
ecs_world_t *world = ecs_mini();
ECS_COMPONENT(world, Position);
ECS_COMPONENT(world, Velocity);
ECS_OBSERVER(world, Remove_from_current, EcsOnSet, Position);
IterData ctx = {.component = ecs_id(Velocity)};
ecs_set_ctx(world, &ctx, NULL);
/* Create entities from scratch so they don't have the EcsName component */
ECS_ENTITY(world, e1, Position, Velocity);
ECS_ENTITY(world, e2, Position, Velocity);
ECS_ENTITY(world, e3, Position, Velocity);
e1 = ecs_set(world, e1, Position, {10, 20});
e2 = ecs_set(world, e2, Position, {11, 21});
e3 = ecs_set(world, e3, Position, {12, 22});
test_assert( ecs_has(world, e1, Position));
test_assert( ecs_has(world, e2, Position));
test_assert( ecs_has(world, e3, Position));
test_assert( !ecs_has(world, e1, Velocity));
test_assert( !ecs_has(world, e2, Velocity));
test_assert( !ecs_has(world, e3, Velocity));
const Position *p = ecs_get(world, e1, Position);
test_int(p->x, 10);
test_int(p->y, 20);
p = ecs_get(world, e2, Position);
test_int(p->x, 11);
test_int(p->y, 21);
p = ecs_get(world, e3, Position);
test_int(p->x, 12);
test_int(p->y, 22);
ecs_fini(world);
}
void ObserverOnSet_remove_set_component_in_on_set(void) {
ecs_world_t *world = ecs_mini();
ECS_COMPONENT(world, Position);
ECS_COMPONENT(world, Velocity);
ECS_OBSERVER(world, Remove_from_current, EcsOnSet, Position);
IterData ctx = {.component = ecs_id(Position)};
ecs_set_ctx(world, &ctx, NULL);
/* Create entities from scratch so they don't have the EcsName component */
ECS_ENTITY(world, e1, Position, Velocity);
ECS_ENTITY(world, e2, Position, Velocity);
ECS_ENTITY(world, e3, Position, Velocity);
e1 = ecs_set(world, e1, Position, {10, 20});
e2 = ecs_set(world, e2, Position, {11, 21});
e3 = ecs_set(world, e3, Position, {12, 22});
test_assert( !ecs_has(world, e1, Position));
test_assert( !ecs_has(world, e2, Position));
test_assert( !ecs_has(world, e3, Position));
test_assert( ecs_has(world, e1, Velocity));
test_assert( ecs_has(world, e2, Velocity));
test_assert( ecs_has(world, e3, Velocity));
ecs_fini(world);
}
void ObserverOnSet_match_table_created_w_add_in_on_set(void) {
ecs_world_t *world = ecs_init();
ECS_COMPONENT(world, Position);
ECS_COMPONENT(world, Velocity);
ECS_COMPONENT(world, Mass);
ECS_OBSERVER(world, Add_to_current, EcsOnSet, Position);
ECS_SYSTEM(world, On_PV, EcsOnUpdate, Position, Velocity);
IterData add_ctx = {.component = ecs_id(Velocity)};
ecs_set_ctx(world, &add_ctx, NULL);
ecs_entity_t e1 = ecs_set(world, 0, Position, {10, 20});
ecs_entity_t e2 = ecs_set(world, 0, Position, {10, 20});
ecs_entity_t e3 = ecs_set(world, 0, Position, {10, 20});
ecs_progress(world, 1);
test_int(pv_probe.count, 3);
test_int(pv_probe.invoked, 1);
test_int(pv_probe.system, On_PV);
test_int(pv_probe.term_count, 2);
test_null(pv_probe.param);
test_int(pv_probe.e[0], e1);
test_int(pv_probe.e[1], e2);
test_int(pv_probe.e[2], e3);
test_int(pv_probe.c[0][0], ecs_id(Position));
test_int(pv_probe.s[0][0], 0);
test_int(pv_probe.c[0][1], ecs_id(Velocity));
test_int(pv_probe.s[0][1], 0);
ecs_fini(world);
}
void ObserverOnSet_set_optional(void) {
ecs_world_t *world = ecs_mini();
ECS_COMPONENT(world, Position);
ECS_COMPONENT(world, Velocity);
ECS_OBSERVER(world, OnPosition, EcsOnSet, Position, ?Velocity);
Probe ctx = { 0 };
ecs_set_ctx(world, &ctx, NULL);
ecs_entity_t e = ecs_new(world, Position);
test_int(ctx.invoked, 0);
ecs_set(world, e, Position, {10, 20});
test_int(ctx.invoked, 1);
test_int(ctx.count, 1);
test_int(ctx.system, OnPosition);
test_int(ctx.term_count, 2);
test_null(ctx.param);
test_int(ctx.e[0], e);
test_int(ctx.c[0][0], ecs_id(Position));
test_int(ctx.s[0][0], 0);
ecs_os_zeromem(&ctx);
ecs_set(world, e, Velocity, {10, 20});
test_int(ctx.invoked, 0);
ecs_fini(world);
}
void ObserverOnSet_set_from_nothing(void) {
ecs_world_t *world = ecs_mini();
ECS_COMPONENT(world, Position);
ECS_COMPONENT(world, Velocity);
ECS_OBSERVER(world, OnPosition, EcsOnSet, Position, Velocity());
Probe ctx = { 0 };
ecs_set_ctx(world, &ctx, NULL);
ecs_entity_t e = ecs_set(world, 0, Position, {10, 20});
test_int(ctx.invoked, 1);
test_int(ctx.count, 1);
test_int(ctx.system, OnPosition);
test_int(ctx.term_count, 2);
test_null(ctx.param);
test_int(ctx.e[0], e);
test_int(ctx.c[0][0], ecs_id(Position));
test_int(ctx.s[0][0], 0);
test_int(ctx.c[0][1], ecs_id(Velocity));
test_int(ctx.s[0][1], 0);
ecs_os_zeromem(&ctx);
ecs_set(world, e, Velocity, {10, 20});
test_int(ctx.invoked, 0);
ecs_fini(world);
}
static
void Add0(ecs_iter_t *it) {
probe_iter(it);
int i;
for (i = 0; i < it->count; i ++) {
ecs_add_id(it->world, it->entities[i], 0);
}
}
void ObserverOnSet_add_0_entity_in_on_set(void) {
install_test_abort();
ecs_world_t *world = ecs_mini();
ECS_COMPONENT(world, Position);
ECS_COMPONENT(world, Velocity);
ECS_OBSERVER(world, Add0, EcsOnSet, Position);
Probe ctx = { 0 };
ecs_set_ctx(world, &ctx, NULL);
test_expect_abort();
ecs_set(world, 0, Position, {10, 20});
}
static int dummy_invoked = 0;
static
void Dummy(ecs_iter_t *it) {
dummy_invoked ++;
}
void ObserverOnSet_on_set_prefab(void) {
ecs_world_t *world = ecs_mini();
ECS_COMPONENT(world, Position);
ECS_OBSERVER(world, Dummy, EcsOnSet, Position);
ECS_PREFAB(world, Prefab, 0);
ecs_set(world, Prefab, Position, {10, 20});
test_int(dummy_invoked, 0);
ecs_fini(world);
}

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,503 @@
#include <api.h>
static ECS_COMPONENT_DECLARE(Position);
static ECS_DECLARE(Tag);
static
void test_no_chain(
ecs_world_t *world,
ecs_poly_t *poly,
ecs_id_t filter)
{
ecs_entity_t e1 = ecs_set(world, 0, Position, {10, 20});
ecs_entity_t e2 = ecs_set(world, 0, Position, {30, 40});
ecs_entity_t e3 = ecs_set(world, 0, Position, {50, 60});
ecs_add(world, e3, Tag);
ecs_iter_t it;
if (filter) {
ecs_term_t term = { .id = filter };
ecs_iter_poly(world, poly, &it, &term);
} else {
ecs_iter_poly(world, poly, &it, NULL);
}
test_assert(ecs_iter_next(&it));
test_int(it.count, 2);
test_int(it.entities[0], e1);
test_int(it.entities[1], e2);
test_int(ecs_field_id(&it, 1), ecs_id(Position));
test_int(ecs_field_src(&it, 1), 0);
test_assert(it.table != NULL);
Position *ptr = ecs_field(&it, Position, 1);
test_assert(ptr != NULL);
test_int(ptr[0].x, 10);
test_int(ptr[0].y, 20);
test_int(ptr[1].x, 30);
test_int(ptr[1].y, 40);
test_assert(ecs_iter_next(&it));
test_int(it.count, 1);
test_int(it.entities[0], e3);
test_int(ecs_field_id(&it, 1), ecs_id(Position));
test_int(ecs_field_src(&it, 1), 0);
test_assert(it.table != NULL);
ptr = ecs_field(&it, Position, 1);
test_assert(ptr != NULL);
test_int(ptr[0].x, 50);
test_int(ptr[0].y, 60);
test_assert(!ecs_iter_next(&it));
}
static
void test_w_chain(
ecs_world_t *world,
ecs_poly_t *poly)
{
ecs_entity_t e1 = ecs_set(world, 0, Position, {10, 20});
ecs_entity_t e2 = ecs_set(world, 0, Position, {30, 40});
ecs_set(world, 0, Position, {50, 60}); // Not matched
ecs_add(world, e1, Tag);
ecs_add(world, e2, Tag);
ecs_iter_t it_arr[2];
ecs_iter_t *it = it_arr;
ecs_iter_poly(world, poly, it_arr, &(ecs_term_t){ .id = Tag});
test_assert(ecs_iter_next(it));
test_int(it->count, 2);
test_int(it->entities[0], e1);
test_int(it->entities[1], e2);
test_int(ecs_field_id(it, 1), Tag);
test_int(ecs_field_src(it, 1), 0);
test_assert(it->table != NULL);
ecs_iter_t *chain_it = it->chain_it;
test_assert(chain_it != NULL);
test_int(chain_it->count, 2);
test_int(chain_it->entities[0], e1);
test_int(chain_it->entities[1], e2);
test_int(ecs_field_id(chain_it, 1), ecs_id(Position));
test_int(ecs_field_src(chain_it, 1), 0);
Position *ptr = ecs_field(chain_it, Position, 1);
test_assert(ptr != NULL);
test_int(ptr[0].x, 10);
test_int(ptr[0].y, 20);
test_int(ptr[1].x, 30);
test_int(ptr[1].y, 40);
test_assert(!ecs_iter_next(it));
}
void Poly_iter_query(void) {
ecs_world_t *world = ecs_mini();
ECS_COMPONENT_DEFINE(world, Position);
ECS_TAG_DEFINE(world, Tag);
ecs_query_t *q = ecs_query_new(world, "Position");
test_assert(q != NULL);
test_no_chain(world, q, 0);
ecs_fini(world);
}
void Poly_iter_query_w_filter(void) {
ecs_world_t *world = ecs_mini();
ECS_COMPONENT_DEFINE(world, Position);
ECS_TAG_DEFINE(world, Tag);
ecs_query_t *q = ecs_query_new(world, "Position");
test_assert(q != NULL);
test_w_chain(world, q);
ecs_fini(world);
}
void Poly_iter_world(void) {
ecs_world_t *world = ecs_mini();
ECS_COMPONENT_DEFINE(world, Position);
ECS_TAG_DEFINE(world, Tag);
ecs_entity_t e1 = ecs_set(world, 0, Position, {10, 20});
ecs_entity_t e2 = ecs_set(world, 0, Position, {30, 40});
ecs_entity_t e3 = ecs_set(world, 0, Position, {50, 60});
ecs_add(world, e3, Tag);
bool e1_found = false;
bool e2_found = false;
bool e3_found = false;
bool position_found = false;
bool tag_found = false;
ecs_iter_t it;
ecs_iter_poly(world, world, &it, 0);
test_assert(ecs_iter_next(&it));
test_assert(it.count != 0);
int i;
for (i = 0; i < it.count; i ++) {
test_assert( ecs_is_alive(world, it.entities[i]));
if (it.entities[i] == e1) e1_found = true;
if (it.entities[i] == e2) e2_found = true;
if (it.entities[i] == e3) e3_found = true;
if (it.entities[i] == ecs_id(Position)) position_found = true;
if (it.entities[i] == Tag) tag_found = true;
}
test_assert(!ecs_iter_next(&it));
test_assert(e1_found);
test_assert(e2_found);
test_assert(e3_found);
test_assert(position_found);
test_assert(tag_found);
ecs_fini(world);
}
void Poly_iter_world_w_filter(void) {
ecs_world_t *world = ecs_mini();
ECS_COMPONENT_DEFINE(world, Position);
ECS_TAG_DEFINE(world, Tag);
test_no_chain(world, world, ecs_id(Position));
ecs_fini(world);
}
void Poly_iter_rule(void) {
ecs_world_t *world = ecs_mini();
ECS_COMPONENT_DEFINE(world, Position);
ECS_TAG_DEFINE(world, Tag);
ecs_rule_t *q = ecs_rule_new(world, "Position");
test_assert(q != NULL);
test_no_chain(world, q, 0);
ecs_rule_fini(q);
ecs_fini(world);
}
void Poly_iter_rule_w_filter(void) {
ecs_world_t *world = ecs_mini();
ECS_COMPONENT_DEFINE(world, Position);
ECS_TAG_DEFINE(world, Tag);
ecs_rule_t *q = ecs_rule_new(world, "Position");
test_assert(q != NULL);
test_w_chain(world, q);
ecs_rule_fini(q);
ecs_fini(world);
}
void Poly_iter_filter(void) {
ecs_world_t *world = ecs_mini();
ECS_COMPONENT_DEFINE(world, Position);
ECS_TAG_DEFINE(world, Tag);
ecs_filter_t *f = ecs_filter_init(world, &(ecs_filter_desc_t){
.expr = "Position"});
test_assert(f != NULL);
test_no_chain(world, f, 0);
ecs_filter_fini(f);
ecs_fini(world);
}
void Poly_iter_filter_w_filter(void) {
ecs_world_t *world = ecs_mini();
ECS_COMPONENT_DEFINE(world, Position);
ECS_TAG_DEFINE(world, Tag);
ecs_filter_t *f = ecs_filter_init(world, &(ecs_filter_desc_t){
.expr = "Position"});
test_assert(f != NULL);
test_w_chain(world, f);
ecs_filter_fini(f);
ecs_fini(world);
}
static
void FooTrigger(ecs_iter_t *it) {}
static
void PolyTrigger(ecs_iter_t *it) {
probe_system_w_ctx(it, it->ctx);
EcsPoly *poly = ecs_field(it, EcsPoly, 1);
test_int(1, it->count);
test_assert(poly->poly != NULL);
}
void Poly_on_set_poly_observer(void) {
ecs_world_t *world = ecs_mini();
ecs_entity_t tag = ecs_new_id(world);
Probe ctx = {0};
ecs_observer_init(world, &(ecs_observer_desc_t){
.filter.terms[0] = { ecs_pair(ecs_id(EcsPoly), EcsObserver) },
.events = { EcsOnSet },
.callback = PolyTrigger,
.ctx = &ctx
});
test_int(1, ctx.invoked);
ecs_os_zeromem(&ctx);
ecs_entity_t t = ecs_observer_init(world, &(ecs_observer_desc_t){
.filter.terms = {{ tag }},
.events = { EcsOnAdd },
.callback = FooTrigger
});
test_int(1, ctx.invoked);
test_int(1, ctx.count);
test_uint(t, ctx.e[0]);
ecs_fini(world);
}
void Poly_on_set_poly_query(void) {
ecs_world_t *world = ecs_mini();
ecs_entity_t tag = ecs_new_id(world);
Probe ctx = {0};
ecs_observer_init(world, &(ecs_observer_desc_t){
.filter.terms[0] = { ecs_pair(ecs_id(EcsPoly), EcsQuery) },
.events = { EcsOnSet },
.callback = PolyTrigger,
.ctx = &ctx
});
test_int(0, ctx.invoked);
ecs_query_init(world, &(ecs_query_desc_t){
.filter.terms = {{ tag }},
});
test_int(1, ctx.invoked);
test_int(1, ctx.count);
ecs_fini(world);
}
void Poly_on_set_poly_system(void) {
ecs_world_t *world = ecs_mini();
ecs_entity_t tag = ecs_new_id(world);
Probe ctx = {0};
ecs_observer_init(world, &(ecs_observer_desc_t){
.filter.terms[0] = { ecs_pair(ecs_id(EcsPoly), EcsSystem) },
.events = { EcsOnSet },
.callback = PolyTrigger,
.ctx = &ctx
});
test_int(0, ctx.invoked);
ecs_entity_t s = ecs_system_init(world, &(ecs_system_desc_t){
.query.filter.terms = {{ tag }},
.callback = FooTrigger
});
test_int(1, ctx.invoked);
test_int(1, ctx.count);
test_uint(s, ctx.e[0]);
ecs_fini(world);
}
void Poly_iter_filter_from_entity(void) {
ecs_world_t *world = ecs_mini();
ECS_TAG(world, Tag);
ecs_entity_t e = ecs_new(world, Tag);
ecs_entity_t qe = ecs_new_id(world);
ecs_filter_t *f = ecs_filter(world, {
.terms = {{ Tag }},
.entity = qe
});
test_assert(f->entity == qe);
const EcsPoly *poly = ecs_get_pair(world, qe, EcsPoly, EcsQuery);
test_assert(poly != NULL);
test_assert(poly->poly == f);
ecs_iter_t it;
ecs_iter_poly(world, poly->poly, &it, NULL);
test_bool(true, ecs_iter_next(&it));
test_int(it.count, 1);
test_uint(it.entities[0], e);
test_bool(false, ecs_iter_next(&it));
ecs_filter_fini(f);
test_assert(!ecs_is_alive(world, qe));
ecs_fini(world);
}
void Poly_iter_query_from_entity(void) {
ecs_world_t *world = ecs_mini();
ECS_TAG(world, Tag);
ecs_entity_t e = ecs_new(world, Tag);
ecs_entity_t qe = ecs_new_id(world);
ecs_query_t *q = ecs_query(world, {
.filter.terms = {{ Tag }},
.filter.entity = qe
});
const EcsPoly *poly = ecs_get_pair(world, qe, EcsPoly, EcsQuery);
test_assert(poly != NULL);
test_assert(poly->poly == q);
ecs_iter_t it;
ecs_iter_poly(world, poly->poly, &it, NULL);
test_bool(true, ecs_iter_next(&it));
test_int(it.count, 1);
test_uint(it.entities[0], e);
test_bool(false, ecs_iter_next(&it));
ecs_query_fini(q);
test_assert(!ecs_is_alive(world, qe));
ecs_fini(world);
}
void Poly_iter_rule_from_entity(void) {
ecs_world_t *world = ecs_mini();
ECS_TAG(world, Tag);
ecs_entity_t e = ecs_new(world, Tag);
ecs_entity_t qe = ecs_new_id(world);
ecs_rule_t *q = ecs_rule(world, {
.terms = {{ Tag }},
.entity = qe
});
const EcsPoly *poly = ecs_get_pair(world, qe, EcsPoly, EcsQuery);
test_assert(poly != NULL);
test_assert(poly->poly == q);
ecs_iter_t it;
ecs_iter_poly(world, poly->poly, &it, NULL);
test_bool(true, ecs_iter_next(&it));
test_int(it.count, 1);
test_uint(it.entities[0], e);
test_bool(false, ecs_iter_next(&it));
ecs_rule_fini(q);
test_assert(!ecs_is_alive(world, qe));
ecs_fini(world);
}
void Poly_free_filter_entity(void) {
ecs_world_t *world = ecs_mini();
ECS_TAG(world, Tag);
ecs_entity_t qe = ecs_new_id(world);
ecs_filter_t *f = ecs_filter(world, {
.terms = {{ Tag }},
.entity = qe
});
test_assert(f->entity == qe);
const EcsPoly *poly = ecs_get_pair(world, qe, EcsPoly, EcsQuery);
test_assert(poly != NULL);
test_assert(poly->poly == f);
ecs_delete(world, qe);
ecs_fini(world);
}
void Poly_free_query_entity(void) {
ecs_world_t *world = ecs_mini();
ECS_TAG(world, Tag);
ecs_entity_t qe = ecs_new_id(world);
ecs_query_t *q = ecs_query(world, {
.filter.terms = {{ Tag }},
.filter.entity = qe
});
const EcsPoly *poly = ecs_get_pair(world, qe, EcsPoly, EcsQuery);
test_assert(poly != NULL);
test_assert(poly->poly == q);
ecs_delete(world, qe);
test_assert(!ecs_is_alive(world, qe));
ecs_fini(world);
}
void Poly_free_rule_entity(void) {
ecs_world_t *world = ecs_mini();
ECS_TAG(world, Tag);
ecs_entity_t qe = ecs_new_id(world);
ecs_rule_t *q = ecs_rule(world, {
.terms = {{ Tag }},
.entity = qe
});
const EcsPoly *poly = ecs_get_pair(world, qe, EcsPoly, EcsQuery);
test_assert(poly != NULL);
test_assert(poly->poly == q);
ecs_delete(world, qe);
ecs_fini(world);
}

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,175 @@
#include <api.h>
void ReadWrite_read(void) {
ecs_world_t *world = ecs_mini();
ECS_COMPONENT(world, Position);
ECS_TAG(world, Tag);
ecs_entity_t e = ecs_set(world, 0, Position, {10, 20});
const ecs_record_t *r = ecs_read_begin(world, e);
test_assert(r != NULL);
const Position *p = ecs_record_get(world, r, Position);
test_assert(p != NULL);
test_int(p->x, 10);
test_int(p->y, 20);
ecs_read_end(r);
ecs_add(world, e, Tag);
test_assert(ecs_has(world, e, Tag));
ecs_fini(world);
}
void ReadWrite_nested_read(void) {
ecs_world_t *world = ecs_mini();
ECS_COMPONENT(world, Position);
ECS_TAG(world, Tag);
ecs_entity_t e = ecs_set(world, 0, Position, {10, 20});
const ecs_record_t *r = ecs_read_begin(world, e);
const ecs_record_t *r_2 = ecs_read_begin(world, e);
test_assert(r != NULL);
test_assert(r_2 != NULL);
test_assert(r == r_2);
const Position *p = ecs_record_get(world, r, Position);
test_assert(p != NULL);
test_int(p->x, 10);
test_int(p->y, 20);
ecs_read_end(r_2);
ecs_read_end(r);
ecs_add(world, e, Tag);
test_assert(ecs_has(world, e, Tag));
ecs_fini(world);
}
void ReadWrite_write(void) {
ecs_world_t *world = ecs_mini();
ECS_COMPONENT(world, Position);
ECS_TAG(world, Tag);
ecs_entity_t e = ecs_set(world, 0, Position, {10, 20});
ecs_record_t *r = ecs_write_begin(world, e);
test_assert(r != NULL);
Position *p = ecs_record_get_mut(world, r, Position);
test_assert(p != NULL);
test_assert(p == ecs_get(world, e, Position));
test_int(p->x, 10);
test_int(p->y, 20);
ecs_write_end(r);
ecs_add(world, e, Tag);
test_assert(ecs_has(world, e, Tag));
ecs_fini(world);
}
void ReadWrite_nested_write(void) {
install_test_abort();
ecs_world_t *world = ecs_mini();
ECS_COMPONENT(world, Position);
ECS_TAG(world, Tag);
ecs_entity_t e = ecs_set(world, 0, Position, {10, 20});
ecs_record_t *r = ecs_write_begin(world, e);
test_assert(r != NULL);
test_expect_abort();
ecs_write_begin(world, e);
}
void ReadWrite_add_while_read(void) {
install_test_abort();
ecs_world_t *world = ecs_mini();
ECS_COMPONENT(world, Position);
ECS_TAG(world, Tag);
ecs_entity_t e = ecs_set(world, 0, Position, {10, 20});
const ecs_record_t *r = ecs_read_begin(world, e);
test_assert(r != NULL);
test_expect_abort();
ecs_add(world, e, Tag);
}
void ReadWrite_add_while_write(void) {
install_test_abort();
ecs_world_t *world = ecs_mini();
ECS_COMPONENT(world, Position);
ECS_TAG(world, Tag);
ecs_entity_t e = ecs_set(world, 0, Position, {10, 20});
ecs_record_t *r = ecs_write_begin(world, e);
test_assert(r != NULL);
test_expect_abort();
ecs_add(world, e, Tag);
}
void ReadWrite_read_from_stage(void) {
ecs_world_t *world = ecs_mini();
ECS_COMPONENT(world, Position);
ECS_TAG(world, Tag);
ecs_entity_t e = ecs_set(world, 0, Position, {10, 20});
ecs_world_t *s = ecs_get_stage(world, 0);
ecs_readonly_begin(world);
const ecs_record_t *r = ecs_read_begin(s, e);
test_assert(r != NULL);
const Position *p = ecs_record_get(s, r, Position);
test_assert(p != NULL);
test_int(p->x, 10);
test_int(p->y, 20);
ecs_read_end(r);
ecs_readonly_end(world);
ecs_add(world, e, Tag);
test_assert(ecs_has(world, e, Tag));
ecs_fini(world);
}
void ReadWrite_write_from_stage(void) {
ecs_world_t *world = ecs_mini();
ECS_COMPONENT(world, Position);
ECS_TAG(world, Tag);
ecs_entity_t e = ecs_set(world, 0, Position, {10, 20});
ecs_world_t *s = ecs_get_stage(world, 0);
ecs_readonly_begin(world);
ecs_record_t *r = ecs_write_begin(s, e);
test_assert(r != NULL);
Position *p = ecs_record_get_mut(s, r, Position);
test_assert(p != NULL);
test_assert(p == ecs_get(world, e, Position));
test_int(p->x, 10);
test_int(p->y, 20);
ecs_write_end(r);
ecs_readonly_end(world);
ecs_add(world, e, Tag);
test_assert(ecs_has(world, e, Tag));
ecs_fini(world);
}

View File

@@ -0,0 +1,314 @@
#include <api.h>
void Reference_setup(void) {
ecs_log_set_level(-3);
}
void Reference_get_ref(void) {
ecs_world_t *world = ecs_mini();
ECS_COMPONENT(world, Position);
ecs_entity_t e = ecs_set(world, 0, Position, {10, 20});
ecs_ref_t ref = ecs_ref_init(world, e, Position);
const Position *p = ecs_ref_get(world, &ref, Position);
test_assert(p != NULL);
test_int(p->x, 10);
test_int(p->y, 20);
ecs_fini(world);
}
void Reference_get_ref_after_add(void) {
ecs_world_t *world = ecs_mini();
ECS_COMPONENT(world, Position);
ECS_COMPONENT(world, Velocity);
ecs_entity_t e = ecs_set(world, 0, Position, {10, 20});
ecs_ref_t ref = ecs_ref_init(world, e, Position);
const Position *p = ecs_ref_get(world, &ref, Position);
test_assert(p != NULL);
test_int(p->x, 10);
test_int(p->y, 20);
ecs_add(world, e, Velocity);
p = ecs_ref_get(world, &ref, Position);
test_assert(p != NULL);
test_int(p->x, 10);
test_int(p->y, 20);
ecs_fini(world);
}
void Reference_get_ref_after_remove(void) {
ecs_world_t *world = ecs_mini();
ECS_COMPONENT(world, Position);
ECS_COMPONENT(world, Velocity);
ecs_entity_t e = ecs_set(world, 0, Position, {10, 20});
ecs_add(world, e, Velocity);
ecs_ref_t ref = ecs_ref_init(world, e, Position);
const Position *p = ecs_ref_get(world, &ref, Position);
test_assert(p != NULL);
test_int(p->x, 10);
test_int(p->y, 20);
ecs_remove(world, e, Velocity);
p = ecs_ref_get(world, &ref, Position);
test_assert(p != NULL);
test_int(p->x, 10);
test_int(p->y, 20);
ecs_fini(world);
}
void Reference_get_ref_after_delete(void) {
ecs_world_t *world = ecs_mini();
ECS_COMPONENT(world, Position);
ecs_entity_t dummy = ecs_new(world, Position);
ecs_entity_t e = ecs_set(world, 0, Position, {10, 20});
ecs_ref_t ref = ecs_ref_init(world, e, Position);
const Position *p = ecs_ref_get(world, &ref, Position);
test_assert(p != NULL);
test_int(p->x, 10);
test_int(p->y, 20);
ecs_delete(world, dummy);
p = ecs_ref_get(world, &ref, Position);
test_assert(p != NULL);
test_int(p->x, 10);
test_int(p->y, 20);
ecs_fini(world);
}
void Reference_get_ref_after_realloc(void) {
ecs_world_t *world = ecs_mini();
ECS_COMPONENT(world, Position);
ecs_entity_t e = ecs_set(world, 0, Position, {10, 20});
ecs_ref_t ref = ecs_ref_init(world, e, Position);
const Position *p = ecs_ref_get(world, &ref, Position);
test_assert(p != NULL);
test_int(p->x, 10);
test_int(p->y, 20);
int i;
for (i = 0; i < 1000; i ++) {
// Creating lots of entities which will trigger allocations
ecs_new(world, Position);
}
p = ecs_ref_get(world, &ref, Position);
test_assert(p != NULL);
test_int(p->x, 10);
test_int(p->y, 20);
ecs_fini(world);
}
void Reference_get_ref_staged(void) {
ecs_world_t *world = ecs_mini();
ECS_COMPONENT(world, Position);
ecs_entity_t e = ecs_set(world, 0, Position, {10, 20});
ecs_ref_t ref = ecs_ref_init(world, e, Position);
const Position *p = ecs_ref_get(world, &ref, Position);
test_assert(p != NULL);
test_int(p->x, 10);
test_int(p->y, 20);
ecs_defer_begin(world);
/* ecs_set() makes immediate changes */
ecs_set(world, e, Position, {30, 40});
p = ecs_ref_get(world, &ref, Position);
test_assert(p != NULL);
test_int(p->x, 30);
test_int(p->y, 40);
ecs_defer_end(world);
p = ecs_ref_get(world, &ref, Position);
test_assert(p != NULL);
test_int(p->x, 30);
test_int(p->y, 40);
ecs_fini(world);
}
void Reference_get_ref_after_new_in_stage(void) {
ecs_world_t *world = ecs_mini();
ECS_COMPONENT(world, Position);
ecs_entity_t e = ecs_set(world, 0, Position, {10, 20});
ecs_ref_t ref = ecs_ref_init(world, e, Position);
const Position *p = ecs_ref_get(world, &ref, Position);
test_assert(p != NULL);
test_int(p->x, 10);
test_int(p->y, 20);
ecs_defer_begin(world);
ecs_new(world, Position);
/* ecs_set() makes immediate changes */
ecs_set(world, e, Position, {30, 40});
p = ecs_ref_get(world, &ref, Position);
test_assert(p != NULL);
test_int(p->x, 30);
test_int(p->y, 40);
ecs_defer_end(world);
p = ecs_ref_get(world, &ref, Position);
test_assert(p != NULL);
test_int(p->x, 30);
test_int(p->y, 40);
ecs_fini(world);
}
void Reference_get_ref_monitored(void) {
ecs_world_t *world = ecs_mini();
ECS_COMPONENT(world, Position);
ECS_COMPONENT(world, Velocity);
ecs_entity_t e = ecs_set(world, 0, Position, {10, 20});
ecs_new_w_pair(world, EcsChildOf, e);
ecs_ref_t ref = ecs_ref_init(world, e, Position);
const Position *p = ecs_ref_get(world, &ref, Position);
test_assert(p != NULL);
test_int(p->x, 10);
test_int(p->y, 20);
ecs_fini(world);
}
void Reference_get_nonexisting(void) {
ecs_world_t *world = ecs_mini();
ECS_COMPONENT(world, Position);
ECS_COMPONENT(world, Velocity);
ecs_entity_t e = ecs_new(world, Position);
ecs_ref_t ref = ecs_ref_init(world, e, Velocity);
const Velocity *p = ecs_ref_get(world, &ref, Velocity);
test_assert(p == NULL);
ecs_fini(world);
}
static ECS_MOVE(Position, dst, src, {
ecs_os_memcpy_t(dst, src, Position);
})
void Reference_get_ref_after_realloc_w_lifecycle(void) {
ecs_world_t *world = ecs_mini();
ECS_COMPONENT(world, Position);
ecs_set_hooks(world, Position, {
.move = ecs_move(Position)
});
ECS_ENTITY(world, e, Position);
ECS_ENTITY(world, e2, Position);
ecs_set(world, e, Position, {10, 20});
ecs_ref_t ref = ecs_ref_init(world, e, Position);
const Position *p = ecs_ref_get(world, &ref, Position);
test_assert(p != NULL);
test_int(p->x, 10);
test_int(p->y, 20);
for (int i = 0; i < 1000; i ++) {
ECS_ENTITY(world, e, Position);
}
p = ecs_ref_get(world, &ref, Position);
test_assert(p != NULL);
test_int(p->x, 10);
test_int(p->y, 20);
ecs_fini(world);
}
void Reference_get_ref_w_low_id_tag(void) {
ecs_world_t *world = ecs_mini();
ecs_entity_t tag = ecs_component_init(world, &(ecs_component_desc_t){
.type.size = 0,
.type.alignment = 0
});
ecs_entity_t comp = ecs_component_init(world, &(ecs_component_desc_t){
.type.size = 4,
.type.alignment = 4
});
ecs_entity_t e = ecs_new_id(world);
ecs_add_id(world, e, tag);
ecs_add_id(world, e, comp);
test_assert(ecs_get_id(world, e, comp) != NULL);
ecs_ref_t ref = ecs_ref_init_id(world, e, comp);
test_assert(ecs_ref_get_id(world, &ref, comp) ==
ecs_get_id(world, e, comp));
ecs_fini(world);
}
void Reference_get_ref_w_low_id_tag_after_add(void) {
ecs_world_t *world = ecs_mini();
ecs_entity_t tag = ecs_component_init(world, &(ecs_component_desc_t){
.type.size = 0,
.type.alignment = 0
});
ecs_entity_t id = ecs_new_low_id(world);
ecs_entity_t comp = ecs_component_init(world, &(ecs_component_desc_t){
.type.size = 4,
.type.alignment = 4
});
ecs_entity_t e = ecs_new_id(world);
ecs_add_id(world, e, tag);
ecs_add_id(world, e, comp);
test_assert(ecs_get_id(world, e, comp) != NULL);
ecs_ref_t ref = ecs_ref_init_id(world, e, comp);
ecs_add_id(world, e, id);
test_assert(ecs_ref_get_id(world, &ref, comp) ==
ecs_get_id(world, e, comp));
ecs_fini(world);
}

View File

@@ -0,0 +1,173 @@
#include <api.h>
void Remove_zero(void) {
install_test_abort();
ecs_world_t *world = ecs_mini();
ecs_entity_t e = ecs_new(world, 0);
test_assert(e != 0);
test_expect_abort();
ecs_remove(world, e, 0);
}
void Remove_1_of_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_remove(world, e, Position);
test_assert(!ecs_has(world, e, Position));
ecs_fini(world);
}
void Remove_1_of_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_remove(world, e, Position);
test_assert(!ecs_has(world, e, Position));
ecs_remove(world, e, Position);
test_assert(!ecs_has(world, e, Position));
ecs_fini(world);
}
void Remove_1_of_2(void) {
ecs_world_t *world = ecs_mini();
ECS_COMPONENT(world, Position);
ECS_COMPONENT(world, Velocity);
ECS_ENTITY(world, e, Position, Velocity);
test_assert(e != 0);
ecs_remove(world, e, Position);
test_assert(!ecs_has(world, e, Position));
test_assert(ecs_has(world, e, Velocity));
ecs_fini(world);
}
void Remove_2_of_2(void) {
ecs_world_t *world = ecs_mini();
ECS_COMPONENT(world, Position);
ECS_COMPONENT(world, Velocity);
ECS_ENTITY(world, e, Position, Velocity);
test_assert(e != 0);
ecs_remove(world, e, Position);
test_assert(!ecs_has(world, e, Position));
test_assert(ecs_has(world, e, Velocity));
ecs_remove(world, e, Velocity);
test_assert(!ecs_has(world, e, Position));
test_assert(!ecs_has(world, e, Velocity));
ecs_fini(world);
}
void Remove_2_of_3(void) {
ecs_world_t *world = ecs_mini();
ECS_COMPONENT(world, Position);
ECS_COMPONENT(world, Velocity);
ECS_COMPONENT(world, Mass);
ECS_ENTITY(world, e, Position, Velocity, Mass);
test_assert(e != 0);
ecs_remove(world, e, Position);
test_assert(!ecs_has(world, e, Position));
test_assert(ecs_has(world, e, Velocity));
test_assert(ecs_has(world, e, Mass));
ecs_remove(world, e, Velocity);
test_assert(!ecs_has(world, e, Position));
test_assert(!ecs_has(world, e, Velocity));
test_assert(ecs_has(world, e, Mass));
ecs_fini(world);
}
void Remove_2_again(void) {
ecs_world_t *world = ecs_mini();
ECS_COMPONENT(world, Position);
ECS_COMPONENT(world, Velocity);
ECS_ENTITY(world, e, Position, Velocity);
test_assert(e != 0);
ecs_remove(world, e, Position);
ecs_remove(world, e, Velocity);
test_assert(!ecs_has(world, e, Position));
test_assert(!ecs_has(world, e, Velocity));
ecs_remove(world, e, Position);
ecs_remove(world, e, Velocity);
test_assert(!ecs_has(world, e, Position));
test_assert(!ecs_has(world, e, Velocity));
ecs_fini(world);
}
void Remove_2_overlap(void) {
ecs_world_t *world = ecs_mini();
ECS_COMPONENT(world, Position);
ECS_COMPONENT(world, Velocity);
ECS_COMPONENT(world, Mass);
ECS_ENTITY(world, e, Position, Velocity, Mass);
test_assert(e != 0);
ecs_remove(world, e, Position);
ecs_remove(world, e, Velocity);
test_assert(!ecs_has(world, e, Position));
test_assert(!ecs_has(world, e, Velocity));
test_assert(ecs_has(world, e, Mass));
ecs_fini(world);
}
void Remove_1_from_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_remove(world, e, Position);
test_assert(!ecs_has(world, e, Position));
ecs_fini(world);
}
void Remove_not_added(void) {
ecs_world_t *world = ecs_mini();
ECS_COMPONENT(world, Position);
ECS_COMPONENT(world, Velocity);
ecs_entity_t e = ecs_new(world, Position);
test_assert(e != 0);
ecs_remove(world, e, Velocity);
test_assert(ecs_has(world, e, Position));
test_assert(!ecs_has(world, e, Velocity));
ecs_fini(world);
}

View File

@@ -0,0 +1,702 @@
#include <api.h>
void Search_search(void) {
ecs_world_t *world = ecs_mini();
ECS_TAG(world, TagA);
ECS_TAG(world, TagB);
ECS_TAG(world, TagC);
ecs_table_t *table = ecs_table_add_id(world, 0, TagA);
table = ecs_table_add_id(world, table, TagB);
table = ecs_table_add_id(world, table, TagC);
ecs_id_t id;
int32_t c = ecs_search(world, table, TagA, &id);
test_int(c, 0);
test_uint(id, TagA);
c = ecs_search(world, table, TagB, &id);
test_int(c, 1);
test_uint(id, TagB);
c = ecs_search(world, table, TagC, &id);
test_int(c, 2);
test_uint(id, TagC);
ecs_fini(world);
}
void Search_search_wildcard(void) {
ecs_world_t *world = ecs_mini();
ECS_TAG(world, Tag);
ECS_TAG(world, Rel);
ECS_TAG(world, ObjA);
ECS_TAG(world, ObjB);
ecs_table_t *table = ecs_table_add_id(world, 0, Tag);
table = ecs_table_add_id(world, table, ecs_pair(Rel, ObjA));
table = ecs_table_add_id(world, table, ecs_pair(Rel, ObjB));
ecs_id_t id;
int32_t c = ecs_search(world, table, ecs_pair(Rel, EcsWildcard), &id);
test_int(c, 1);
test_uint(id, ecs_pair(Rel, ObjA));
ecs_fini(world);
}
void Search_search_wildcard_w_offset(void) {
ecs_world_t *world = ecs_mini();
ECS_TAG(world, Tag);
ECS_TAG(world, Rel);
ECS_TAG(world, ObjA);
ECS_TAG(world, ObjB);
ECS_TAG(world, ObjC);
ecs_table_t *table = ecs_table_add_id(world, 0, Tag);
table = ecs_table_add_id(world, table, ecs_pair(Rel, ObjA));
table = ecs_table_add_id(world, table, ecs_pair(Rel, ObjB));
table = ecs_table_add_id(world, table, ecs_pair(Rel, ObjC));
ecs_id_t id;
int32_t c = ecs_search(world, table, ecs_pair(Rel, EcsWildcard), &id);
test_int(c, 1);
test_uint(id, ecs_pair(Rel, ObjA));
c = ecs_search_offset(world, table, 2, ecs_pair(Rel, EcsWildcard), &id);
test_int(c, 2);
test_uint(id, ecs_pair(Rel, ObjB));
c = ecs_search_offset(world, table, 3, ecs_pair(Rel, EcsWildcard), &id);
test_int(c, 3);
test_uint(id, ecs_pair(Rel, ObjC));
c = ecs_search_offset(world, table, 4, ecs_pair(Rel, EcsWildcard), &id);
test_int(c, -1);
ecs_fini(world);
}
void Search_search_relation_wildcard_w_offset(void) {
ecs_world_t *world = ecs_mini();
ECS_TAG(world, Tag);
ECS_TAG(world, RelX);
ECS_TAG(world, RelY);
ECS_TAG(world, RelZ);
ECS_TAG(world, ObjA);
ECS_TAG(world, ObjB);
ecs_table_t *table = ecs_table_add_id(world, 0, Tag);
table = ecs_table_add_id(world, table, ecs_pair(RelX, ObjA));
table = ecs_table_add_id(world, table, ecs_pair(RelX, ObjB));
table = ecs_table_add_id(world, table, ecs_pair(RelY, ObjA));
table = ecs_table_add_id(world, table, ecs_pair(RelY, ObjB));
table = ecs_table_add_id(world, table, ecs_pair(RelZ, ObjA));
table = ecs_table_add_id(world, table, ecs_pair(RelZ, ObjB));
ecs_id_t id;
int32_t c = ecs_search(world, table, ecs_pair(EcsWildcard, ObjB), &id);
test_int(c, 2);
test_uint(id, ecs_pair(RelX, ObjB));
c = ecs_search_offset(world, table, 3, ecs_pair(EcsWildcard, ObjB), &id);
test_int(c, 4);
test_uint(id, ecs_pair(RelY, ObjB));
c = ecs_search_offset(world, table, 5, ecs_pair(EcsWildcard, ObjB), &id);
test_int(c, 6);
test_uint(id, ecs_pair(RelZ, ObjB));
c = ecs_search_offset(world, table, 7, ecs_pair(EcsWildcard, ObjB), &id);
test_int(c, -1);
ecs_fini(world);
}
void Search_search_pair_w_any_rel(void) {
ecs_world_t *world = ecs_mini();
ECS_TAG(world, Tag);
ECS_TAG(world, Rel);
ECS_TAG(world, ObjA);
ECS_TAG(world, ObjB);
ecs_table_t *table = ecs_table_add_id(world, 0, Tag);
table = ecs_table_add_id(world, table, ecs_pair(Rel, ObjA));
table = ecs_table_add_id(world, table, ecs_pair(Rel, ObjB));
ecs_id_t id;
int32_t c = ecs_search(world, table, ecs_pair(EcsAny, ObjB), &id);
test_int(c, 2);
test_uint(id, ecs_pair(Rel, ObjB));
ecs_fini(world);
}
void Search_search_pair_w_any_obj(void) {
ecs_world_t *world = ecs_mini();
ECS_TAG(world, Tag);
ECS_TAG(world, Rel);
ECS_TAG(world, ObjA);
ECS_TAG(world, ObjB);
ecs_table_t *table = ecs_table_add_id(world, 0, Tag);
table = ecs_table_add_id(world, table, ecs_pair(Rel, ObjA));
table = ecs_table_add_id(world, table, ecs_pair(Rel, ObjB));
ecs_id_t id;
int32_t c = ecs_search(world, table, ecs_pair(Rel, EcsAny), &id);
test_int(c, 1);
test_uint(id, ecs_pair(Rel, ObjA));
ecs_fini(world);
}
void Search_search_follow_relation_lvl_0(void) {
ecs_world_t *world = ecs_mini();
ECS_TAG(world, TagA);
ECS_TAG(world, TagB);
ECS_TAG(world, Rel);
ecs_entity_t e_0 = ecs_new(world, TagA);
ecs_add(world, e_0, TagB);
ecs_table_t *t = ecs_get_table(world, e_0);
ecs_entity_t subj = 0;
ecs_id_t id = 0;
int32_t c = ecs_search_relation(world, t, 0, TagB, Rel, 0, &subj, &id, 0);
test_int(c, 1);
test_uint(id, TagB);
test_uint(subj, 0);
ecs_fini(world);
}
void Search_search_follow_relation_lvl_1(void) {
ecs_world_t *world = ecs_mini();
ECS_TAG(world, TagA);
ECS_TAG(world, TagB);
ECS_TAG(world, Rel);
ecs_entity_t e_0 = ecs_new(world, TagA);
ecs_add(world, e_0, TagB);
ecs_entity_t e_1 = ecs_new_w_pair(world, Rel, e_0);
ecs_table_t *t = ecs_get_table(world, e_1);
ecs_entity_t subj = 0;
ecs_id_t id = 0;
int32_t c = ecs_search_relation(world, t, 0, TagB, Rel, 0, &subj, &id, 0);
test_int(c, 0);
test_uint(id, TagB);
test_uint(subj, e_0);
ecs_fini(world);
}
void Search_search_follow_relation_lvl_2(void) {
ecs_world_t *world = ecs_mini();
ECS_TAG(world, TagA);
ECS_TAG(world, TagB);
ECS_TAG(world, Rel);
ecs_entity_t e_0 = ecs_new(world, TagA);
ecs_add(world, e_0, TagB);
ecs_entity_t e_1 = ecs_new_w_pair(world, Rel, e_0);
ecs_entity_t e_2 = ecs_new_w_pair(world, Rel, e_1);
ecs_table_t *t = ecs_get_table(world, e_2);
ecs_entity_t subj = 0;
ecs_id_t id = 0;
int32_t c = ecs_search_relation(world, t, 0, TagB, Rel, 0, &subj, &id, 0);
test_int(c, 0);
test_uint(id, TagB);
test_uint(subj, e_0);
ecs_fini(world);
}
void Search_search_follow_relation_lvl_3(void) {
ecs_world_t *world = ecs_mini();
ECS_TAG(world, TagA);
ECS_TAG(world, TagB);
ECS_TAG(world, Rel);
ecs_entity_t e_0 = ecs_new(world, TagA);
ecs_add(world, e_0, TagB);
ecs_entity_t e_1 = ecs_new_w_pair(world, Rel, e_0);
ecs_entity_t e_2 = ecs_new_w_pair(world, Rel, e_1);
ecs_entity_t e_3 = ecs_new_w_pair(world, Rel, e_2);
ecs_table_t *t = ecs_get_table(world, e_3);
ecs_entity_t subj = 0;
ecs_id_t id = 0;
int32_t c = ecs_search_relation(world, t, 0, TagB, Rel, 0, &subj, &id, 0);
test_int(c, 0);
test_uint(id, TagB);
test_uint(subj, e_0);
ecs_fini(world);
}
void Search_search_first_lvl_0(void) {
ecs_world_t *world = ecs_mini();
ECS_TAG(world, TagA);
ECS_TAG(world, TagB);
ECS_TAG(world, Rel);
ecs_entity_t e_0 = ecs_new(world, TagA);
ecs_add(world, e_0, TagB);
ecs_table_t *t = ecs_get_table(world, e_0);
ecs_entity_t subj = 0;
ecs_id_t id = 0;
int32_t c = ecs_search_relation(world, t, 0, TagB, Rel, 0, &subj, &id, 0);
test_int(c, 1);
test_uint(id, TagB);
test_uint(subj, 0);
ecs_fini(world);
}
void Search_search_first_lvl_1(void) {
ecs_world_t *world = ecs_mini();
ECS_TAG(world, TagA);
ECS_TAG(world, TagB);
ECS_TAG(world, Rel);
ecs_entity_t e_0 = ecs_new(world, TagA);
ecs_entity_t e_1 = ecs_new_w_pair(world, Rel, e_0);
ecs_add(world, e_0, TagB);
ecs_table_t *t = ecs_get_table(world, e_1);
ecs_entity_t subj = 0;
ecs_id_t id = 0;
int32_t c = ecs_search_relation(world, t, 0, TagB, Rel, 0, &subj, &id, 0);
test_int(c, 0);
test_uint(id, TagB);
test_uint(subj, e_0);
ecs_fini(world);
}
void Search_search_first_lvl_2(void) {
ecs_world_t *world = ecs_mini();
ECS_TAG(world, TagA);
ECS_TAG(world, TagB);
ECS_TAG(world, Rel);
ecs_entity_t e_0 = ecs_new(world, TagA);
ecs_entity_t e_1 = ecs_new_w_pair(world, Rel, e_0);
ecs_entity_t e_2 = ecs_new_w_pair(world, Rel, e_1);
ecs_add(world, e_0, TagB);
ecs_add(world, e_1, TagB);
ecs_table_t *t = ecs_get_table(world, e_2);
ecs_entity_t subj = 0;
ecs_id_t id = 0;
int32_t c = ecs_search_relation(world, t, 0, TagB, Rel, 0, &subj, &id, 0);
test_int(c, 0);
test_uint(id, TagB);
test_uint(subj, e_1);
ecs_fini(world);
}
void Search_search_first_lvl_3(void) {
ecs_world_t *world = ecs_mini();
ECS_TAG(world, TagA);
ECS_TAG(world, TagB);
ECS_TAG(world, Rel);
ecs_entity_t e_0 = ecs_new(world, TagA);
ecs_entity_t e_1 = ecs_new_w_pair(world, Rel, e_0);
ecs_entity_t e_2 = ecs_new_w_pair(world, Rel, e_1);
ecs_entity_t e_3 = ecs_new_w_pair(world, Rel, e_2);
ecs_add(world, e_0, TagB);
ecs_add(world, e_1, TagB);
ecs_add(world, e_2, TagB);
ecs_table_t *t = ecs_get_table(world, e_3);
ecs_entity_t subj = 0;
ecs_id_t id = 0;
int32_t c = ecs_search_relation(world, t, 0, TagB, Rel, 0, &subj, &id, 0);
test_int(c, 0);
test_uint(id, TagB);
test_uint(subj, e_2);
ecs_fini(world);
}
void Search_search_relation_wildcard(void) {
ecs_world_t *world = ecs_mini();
ECS_TAG(world, Tag);
ECS_TAG(world, TgtA);
ECS_TAG(world, TgtB);
ECS_TAG(world, Rel);
ecs_entity_t b = ecs_new(world, Tag);
ecs_add(world, b, Tag);
ecs_add_pair(world, b, Rel, TgtA);
ecs_add_pair(world, b, Rel, TgtB);
ecs_entity_t e = ecs_new_id(world);
ecs_add_pair(world, e, EcsChildOf, b);
ecs_table_t *table = ecs_get_table(world, e);
ecs_entity_t subj = 0;
ecs_id_t id = 0;
int32_t column = 0;
column = ecs_search_relation(world, table, 0, ecs_pair(Rel, EcsWildcard),
EcsChildOf, EcsUp, &subj, &id, 0);
test_int(column, 0);
test_uint(subj, b);
test_uint(id, ecs_pair(Rel, TgtA));
ecs_fini(world);
}
void Search_search_relation_at_offset(void) {
ecs_world_t *world = ecs_mini();
ECS_TAG(world, Tag);
ECS_TAG(world, Rel);
ecs_entity_t b1 = ecs_new(world, Tag);
ecs_entity_t b2 = ecs_new(world, Tag);
ecs_entity_t e = ecs_new_id(world);
ecs_add_pair(world, e, Rel, b1);
ecs_add_pair(world, e, Rel, b2);
ecs_table_t *table = ecs_get_table(world, e);
ecs_entity_t subj = 0;
ecs_id_t id = 0;
int32_t column = 0;
column = ecs_search_relation(world, table, 0, Tag, Rel, EcsUp, &subj, &id, 0);
test_int(column, 0);
test_uint(subj, b1);
test_uint(id, Tag);
subj = 0;
column = ecs_search_relation(
world, table, 1, Tag, Rel, EcsUp, &subj, &id, 0);
test_int(column, 1);
test_uint(subj, b2);
test_uint(id, Tag);
ecs_fini(world);
}
void Search_search_relation_inherit_from_parent(void) {
ecs_world_t *world = ecs_mini();
ECS_TAG(world, TagA);
ECS_TAG(world, TagB);
ECS_TAG(world, TagC);
ecs_entity_t b = ecs_new_id(world);
ecs_add(world, b, TagA);
ecs_add(world, b, TagB);
ecs_entity_t p = ecs_new_id(world);
ecs_add_pair(world, p, EcsIsA, b);
ecs_add(world, p, TagC);
ecs_entity_t e = ecs_new_id(world);
ecs_add(world, e, TagA);
ecs_add(world, e, TagB);
ecs_add(world, e, TagC);
ecs_add_pair(world, e, EcsChildOf, p);
ecs_table_t *table = ecs_get_table(world, e);
ecs_entity_t subj = 0;
ecs_id_t id = 0;
int32_t column = 0;
column = ecs_search_relation(world, table, 0, TagA, EcsChildOf, EcsUp, &subj, &id, 0);
test_int(column, 3);
test_int(subj, b);
test_int(id, TagA);
column = ecs_search_relation(world, table, 0, TagB, EcsChildOf, EcsUp, &subj, &id, 0);
test_int(column, 3);
test_int(subj, b);
test_int(id, TagB);
column = ecs_search_relation(world, table, 0, TagC, EcsChildOf, EcsUp, &subj, &id, 0);
test_int(column, 3);
test_int(subj, p);
test_int(id, TagC);
ecs_fini(world);
}
void Search_search_relation_dont_inherit(void) {
ecs_world_t *world = ecs_mini();
ECS_TAG(world, TagA);
ECS_TAG(world, TagB);
ECS_TAG(world, TagC);
ecs_add_id(world, TagB, EcsDontInherit);
ecs_entity_t b = ecs_new_id(world);
ecs_add(world, b, TagA);
ecs_add(world, b, TagB);
ecs_add(world, b, TagC);
ecs_entity_t e = ecs_new_id(world);
ecs_add(world, e, TagA);
ecs_add(world, e, TagB);
ecs_add(world, e, TagC);
ecs_add_pair(world, e, EcsIsA, b);
ecs_table_t *table = ecs_get_table(world, e);
ecs_entity_t subj = 0;
ecs_id_t id = 0;
int32_t column = 0;
column = ecs_search_relation(world, table, 0, TagA, EcsIsA, EcsUp, &subj, &id, 0);
test_int(column, 3);
test_int(subj, b);
test_int(id, TagA);
column = ecs_search_relation(world, table, 0, TagB, EcsIsA, EcsUp, &subj, &id, 0);
test_int(column, -1);
column = ecs_search_relation(world, table, 0, TagC, EcsIsA, EcsUp, &subj, &id, 0);
test_int(column, 3);
test_int(subj, b);
test_int(id, TagC);
column = ecs_search_relation(world, table, 0, TagB, EcsIsA, EcsSelf|EcsUp, &subj, &id, 0);
test_int(column, 1);
test_int(subj, 0);
test_int(id, TagB);
column = ecs_search_relation(world, table, 0, TagB, EcsIsA, EcsSelf, &subj, &id, 0);
test_int(column, 1);
test_int(subj, 0);
test_int(id, TagB);
ecs_fini(world);
}
void Search_search_relation_dont_inherit_from_parent(void) {
ecs_world_t *world = ecs_mini();
ECS_TAG(world, TagA);
ECS_TAG(world, TagB);
ECS_TAG(world, TagC);
ecs_add_id(world, TagB, EcsDontInherit);
ecs_entity_t b = ecs_new_id(world);
ecs_add(world, b, TagA);
ecs_add(world, b, TagB);
ecs_entity_t p = ecs_new_id(world);
ecs_add_pair(world, p, EcsIsA, b);
ecs_add(world, p, TagC);
ecs_entity_t e = ecs_new_id(world);
ecs_add(world, e, TagA);
ecs_add(world, e, TagB);
ecs_add(world, e, TagC);
ecs_add_pair(world, e, EcsChildOf, p);
ecs_table_t *table = ecs_get_table(world, e);
ecs_entity_t subj = 0;
ecs_id_t id = 0;
int32_t column = 0;
column = ecs_search_relation(world, table, 0, TagA, EcsChildOf, EcsUp, &subj, &id, 0);
test_int(column, 3);
test_int(subj, b);
test_int(id, TagA);
column = ecs_search_relation(world, table, 0, TagB, EcsChildOf, EcsUp, &subj, &id, 0);
test_int(column, -1);
column = ecs_search_relation(world, table, 0, TagC, EcsChildOf, EcsUp, &subj, &id, 0);
test_int(column, 3);
test_int(subj, p);
test_int(id, TagC);
column = ecs_search_relation(world, table, 0, TagB, EcsChildOf, EcsSelf|EcsUp, &subj, &id, 0);
test_int(column, 1);
test_int(subj, 0);
test_int(id, TagB);
column = ecs_search_relation(world, table, 0, TagB, EcsChildOf, EcsSelf, &subj, &id, 0);
test_int(column, 1);
test_int(subj, 0);
test_int(id, TagB);
ecs_fini(world);
}
void Search_search_relation_exclusive(void) {
ecs_world_t *world = ecs_mini();
ECS_TAG(world, TagA);
ECS_TAG(world, TagB);
ECS_TAG(world, Rel);
ecs_add_id(world, Rel, EcsExclusive);
ecs_entity_t b = ecs_new_id(world);
ecs_add_pair(world, b, Rel, TagA);
ecs_entity_t e = ecs_new_id(world);
ecs_add_pair(world, e, Rel, TagB);
ecs_add_pair(world, e, EcsIsA, b);
ecs_table_t *table = ecs_get_table(world, e);
ecs_entity_t subj = 0;
ecs_id_t id = 0;
int32_t column = 0;
column = ecs_search_relation(world, table, 0, ecs_pair(Rel, TagA), EcsIsA, EcsSelf|EcsUp, &subj, &id, 0);
test_int(column, -1);
column = ecs_search_relation(world, table, 0, ecs_pair(Rel, TagB), EcsIsA, EcsSelf|EcsUp, &subj, &id, 0);
test_int(column, 1);
test_int(subj, 0);
test_int(id, ecs_pair(Rel, TagB));
column = ecs_search_relation(world, table, 0, ecs_pair(Rel, TagA), EcsIsA, EcsUp, &subj, &id, 0);
test_int(column, -1);
column = ecs_search_relation(world, table, 0, ecs_pair(Rel, TagB), EcsIsA, EcsUp, &subj, &id, 0);
test_int(column, -1);
ecs_fini(world);
}
void Search_search_relation_union(void) {
ecs_world_t *world = ecs_mini();
ECS_TAG(world, TagA);
ECS_TAG(world, TagB);
ECS_TAG(world, Rel);
ecs_add_id(world, Rel, EcsUnion);
ecs_entity_t b = ecs_new_id(world);
ecs_add_pair(world, b, Rel, TagA);
ecs_entity_t e = ecs_new_id(world);
ecs_add_pair(world, e, EcsIsA, b);
ecs_table_t *table = ecs_get_table(world, e);
ecs_entity_t subj = 0;
ecs_id_t id = 0;
int32_t column = 0;
column = ecs_search_relation(world, table, 0, ecs_pair(Rel, TagA), EcsIsA, EcsSelf|EcsUp, &subj, &id, 0);
test_int(column, 0);
test_int(subj, b);
test_int(id, ecs_pair(Rel, EcsWildcard));
column = ecs_search_relation(world, table, 0, ecs_pair(Rel, TagA), EcsIsA, EcsUp, &subj, &id, 0);
test_int(column, 0);
test_int(subj, b);
test_int(id, ecs_pair(Rel, EcsWildcard));
column = ecs_search_relation(world, table, 0, ecs_pair(Rel, TagA), EcsIsA, EcsSelf, &subj, &id, 0);
test_int(column, -1);
ecs_fini(world);
}
void Search_search_relation_union_wildcard(void) {
ecs_world_t *world = ecs_mini();
ECS_TAG(world, TagA);
ECS_TAG(world, TagB);
ECS_TAG(world, Rel);
ecs_add_id(world, Rel, EcsUnion);
ecs_entity_t b = ecs_new_id(world);
ecs_add_pair(world, b, Rel, TagA);
ecs_entity_t e = ecs_new_id(world);
ecs_add_pair(world, e, EcsIsA, b);
ecs_table_t *table = ecs_get_table(world, e);
ecs_entity_t subj = 0;
ecs_id_t id = 0;
int32_t column = 0;
column = ecs_search_relation(world, table, 0, ecs_pair(Rel, EcsWildcard), EcsIsA, EcsSelf|EcsUp, &subj, &id, 0);
test_int(column, 0);
test_int(subj, b);
test_int(id, ecs_pair(Rel, EcsWildcard));
column = ecs_search_relation(world, table, 0, ecs_pair(Rel, EcsWildcard), EcsIsA, EcsUp, &subj, &id, 0);
test_int(column, 0);
test_int(subj, b);
test_int(id, ecs_pair(Rel, EcsWildcard));
column = ecs_search_relation(world, table, 0, ecs_pair(Rel, EcsWildcard), EcsIsA, EcsSelf, &subj, &id, 0);
test_int(column, -1);
ecs_fini(world);
}
void Search_search_relation_union_pair(void) {
ecs_world_t *world = ecs_mini();
ECS_TAG(world, TagA);
ECS_TAG(world, TagB);
ECS_TAG(world, Rel);
ecs_add_id(world, Rel, EcsUnion);
ecs_entity_t b = ecs_new_id(world);
ecs_add_pair(world, b, Rel, TagA);
ecs_entity_t e = ecs_new_id(world);
ecs_add_pair(world, e, EcsIsA, b);
ecs_table_t *table = ecs_get_table(world, e);
ecs_entity_t subj = 0;
ecs_id_t id = 0;
int32_t column = 0;
column = ecs_search_relation(world, table, 0, ecs_pair(EcsUnion, Rel), EcsIsA, EcsSelf|EcsUp, &subj, &id, 0);
test_int(column, 0);
test_int(subj, b);
test_int(id, ecs_pair(EcsUnion, Rel));
column = ecs_search_relation(world, table, 0, ecs_pair(EcsUnion, Rel), EcsIsA, EcsUp, &subj, &id, 0);
test_int(column, 0);
test_int(subj, b);
test_int(id, ecs_pair(EcsUnion, Rel));
column = ecs_search_relation(world, table, 0, ecs_pair(EcsUnion, Rel), EcsIsA, EcsSelf, &subj, &id, 0);
test_int(column, -1);
ecs_fini(world);
}

View File

@@ -0,0 +1,727 @@
#include <api.h>
void Set_set_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_set(world, e, Position, {10, 20});
test_assert(ecs_has(world, e, Position));
const Position *p = ecs_get(world, e, Position);
test_assert(p != NULL);
test_int(p->x, 10);
test_int(p->y, 20);
ecs_fini(world);
}
void Set_set_nonempty(void) {
ecs_world_t *world = ecs_mini();
ECS_COMPONENT(world, Position);
ECS_COMPONENT(world, Velocity);
ecs_entity_t e = ecs_new(world, Position);
test_assert(e != 0);
ecs_set(world, e, Velocity, {10, 20});
test_assert(ecs_has(world, e, Position));
test_assert(ecs_has(world, e, Velocity));
const Velocity *v = ecs_get(world, e, Velocity);
test_assert(v != NULL);
test_int(v->x, 10);
test_int(v->y, 20);
ecs_fini(world);
}
void Set_set_non_empty_override(void) {
ecs_world_t *world = ecs_mini();
ECS_COMPONENT(world, Position);
ecs_entity_t e = ecs_new(world, Position);
test_assert(e != 0);
ecs_set(world, e, Position, {10, 20});
test_assert(ecs_has(world, e, Position));
const Position *p = ecs_get(world, e, Position);
test_assert(p != NULL);
test_int(p->x, 10);
test_int(p->y, 20);
ecs_fini(world);
}
void Set_set_again(void) {
ecs_world_t *world = ecs_mini();
ECS_COMPONENT(world, Position);
ecs_entity_t e = ecs_new(world, 0);
test_assert(e != 0);
ecs_set(world, e, Position, {10, 20});
test_assert(ecs_has(world, e, Position));
const Position *p = ecs_get(world, e, Position);
test_assert(p != NULL);
test_int(p->x, 10);
test_int(p->y, 20);
ecs_set(world, e, Position, {30, 40});
test_assert(ecs_has(world, e, Position));
p = ecs_get(world, e, Position);
test_assert(p != NULL);
test_int(p->x, 30);
test_int(p->y, 40);
ecs_fini(world);
}
void Set_set_2(void) {
ecs_world_t *world = ecs_mini();
ECS_COMPONENT(world, Position);
ECS_COMPONENT(world, Velocity);
ecs_entity_t e = ecs_new(world, 0);
test_assert(e != 0);
ecs_set(world, e, Position, {10, 20});
test_assert(ecs_has(world, e, Position));
const Position *p = ecs_get(world, e, Position);
test_assert(p != NULL);
test_int(p->x, 10);
test_int(p->y, 20);
ecs_set(world, e, Velocity, {30, 40});
test_assert(ecs_has(world, e, Position));
test_assert(ecs_has(world, e, Velocity));
p = ecs_get(world, e, Position);
test_assert(p != NULL);
test_int(p->x, 10);
test_int(p->y, 20);
const Velocity *v = ecs_get(world, e, Velocity);
test_assert(v != NULL);
test_int(v->x, 30);
test_int(v->y, 40);
ecs_fini(world);
}
void Set_add_set(void) {
ecs_world_t *world = ecs_mini();
ECS_COMPONENT(world, Position);
ecs_entity_t e = ecs_new(world, 0);
test_assert(e != 0);
ecs_add(world, e, Position);
test_assert(ecs_has(world, e, Position));
ecs_set(world, e, Position, {10, 20});
test_assert(ecs_has(world, e, Position));
const Position *p = ecs_get(world, e, Position);
test_assert(p != NULL);
test_int(p->x, 10);
test_int(p->y, 20);
ecs_fini(world);
}
void Set_set_add(void) {
ecs_world_t *world = ecs_mini();
ECS_COMPONENT(world, Position);
ecs_entity_t e = ecs_new(world, 0);
test_assert(e != 0);
ecs_set(world, e, Position, {10, 20});
test_assert(ecs_has(world, e, Position));
const Position *p = ecs_get(world, e, Position);
test_assert(p != NULL);
test_int(p->x, 10);
test_int(p->y, 20);
ecs_add(world, e, Position);
test_assert(ecs_has(world, e, Position));
p = ecs_get(world, e, Position);
test_assert(p != NULL);
test_int(p->x, 10);
test_int(p->y, 20);
ecs_fini(world);
}
void Set_set_add_other(void) {
ecs_world_t *world = ecs_mini();
ECS_COMPONENT(world, Position);
ECS_COMPONENT(world, Velocity);
ecs_entity_t e = ecs_new(world, 0);
test_assert(e != 0);
ecs_set(world, e, Position, {10, 20});
test_assert(ecs_has(world, e, Position));
const Position *p = ecs_get(world, e, Position);
test_assert(p != NULL);
test_int(p->x, 10);
test_int(p->y, 20);
ecs_add(world, e, Velocity);
test_assert(ecs_has(world, e, Position));
test_assert(ecs_has(world, e, Velocity));
p = ecs_get(world, e, Position);
test_assert(p != NULL);
test_int(p->x, 10);
test_int(p->y, 20);
ecs_fini(world);
}
void Set_set_remove(void) {
ecs_world_t *world = ecs_mini();
ECS_COMPONENT(world, Position);
ecs_entity_t e = ecs_new(world, 0);
test_assert(e != 0);
ecs_set(world, e, Position, {10, 20});
test_assert(ecs_has(world, e, Position));
const Position *p = ecs_get(world, e, Position);
test_assert(p != NULL);
test_int(p->x, 10);
test_int(p->y, 20);
ecs_remove(world, e, Position);
test_assert(!ecs_has(world, e, Position));
p = ecs_get(world, e, Position);
test_assert(p == NULL);
ecs_fini(world);
}
void Set_set_remove_other(void) {
ecs_world_t *world = ecs_mini();
ECS_COMPONENT(world, Position);
ECS_COMPONENT(world, Velocity);
ecs_entity_t e = ecs_new(world, Velocity);
test_assert(e != 0);
ecs_set(world, e, Position, {10, 20});
test_assert(ecs_has(world, e, Position));
test_assert(ecs_has(world, e, Velocity));
const Position *p = ecs_get(world, e, Position);
test_assert(p != NULL);
test_int(p->x, 10);
test_int(p->y, 20);
ecs_remove(world, e, Velocity);
test_assert(ecs_has(world, e, Position));
test_assert(!ecs_has(world, e, Velocity));
p = ecs_get(world, e, Position);
test_assert(p != NULL);
test_int(p->x, 10);
test_int(p->y, 20);
ecs_fini(world);
}
void Set_set_remove_twice(void) {
ecs_world_t *world = ecs_mini();
ECS_COMPONENT(world, Position);
ecs_entity_t e = ecs_new(world, 0);
test_assert(e != 0);
ecs_set(world, e, Position, {10, 20});
test_assert(ecs_has(world, e, Position));
const Position *p = ecs_get(world, e, Position);
test_assert(p != NULL);
test_int(p->x, 10);
test_int(p->y, 20);
ecs_remove(world, e, Position);
test_assert(!ecs_has(world, e, Position));
p = ecs_get(world, e, Position);
test_assert(p == NULL);
ecs_set(world, e, Position, {10, 20});
test_assert(ecs_has(world, e, Position));
p = ecs_get(world, e, Position);
test_assert(p != NULL);
test_int(p->x, 10);
test_int(p->y, 20);
ecs_fini(world);
}
void Set_set_and_new(void) {
ecs_world_t *world = ecs_mini();
ECS_COMPONENT(world, Position);
ecs_entity_t e = ecs_set(world, 0, Position, {10, 20});
test_assert(e != 0);
test_assert(ecs_has(world, e, Position));
const Position *p = ecs_get(world, e, Position);
test_assert(p != NULL);
test_int(p->x, 10);
test_int(p->y, 20);
ecs_fini(world);
}
void Set_set_null(void) {
ecs_world_t *world = ecs_mini();
ECS_COMPONENT(world, Position);
ecs_entity_t e = ecs_new(world, 0);
ecs_set_ptr(world, e, Position, NULL);
test_assert(e != 0);
test_assert(ecs_has(world, e, Position));
const Position *p = ecs_get(world, e, Position);
test_assert(p != NULL);
test_int(p->x, 0);
test_int(p->y, 0);
ecs_fini(world);
}
void Set_get_mut_new(void) {
ecs_world_t *world = ecs_mini();
ECS_COMPONENT(world, Position);
ecs_entity_t e = ecs_new(world, 0);
test_assert(e != 0);
Position *p = ecs_get_mut(world, e, Position);
test_assert(p != NULL);
test_assert( ecs_has(world, e, Position));
test_assert(p == ecs_get(world, e, Position));
ecs_fini(world);
}
void Set_get_mut_existing(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_has(world, e, Position));
const Position *p_prev = ecs_get(world, e, Position);
Position *p = ecs_get_mut(world, e, Position);
test_assert(p != NULL);
test_assert( ecs_has(world, e, Position));
test_assert(p == p_prev);
ecs_fini(world);
}
void Set_get_mut_tag_new(void) {
install_test_abort();
ecs_world_t *world = ecs_mini();
ECS_TAG(world, MyTag);
ecs_entity_t e = ecs_new(world, 0);
test_assert(e != 0);
test_expect_abort();
ecs_get_mut_id(world, e, MyTag);
}
void Set_get_mut_tag_existing(void) {
install_test_abort();
ecs_world_t *world = ecs_mini();
ECS_TAG(world, MyTag);
ecs_entity_t e = ecs_new(world, MyTag);
test_assert(e != 0);
test_assert( ecs_has(world, e, MyTag));
test_expect_abort();
ecs_get_mut_id(world, e, MyTag);
}
void Set_get_mut_tag_new_w_comp(void) {
install_test_abort();
ecs_world_t *world = ecs_mini();
ECS_COMPONENT(world, Position);
ECS_TAG(world, MyTag);
ecs_entity_t e = ecs_new(world, Position);
test_assert(e != 0);
test_expect_abort();
ecs_get_mut_id(world, e, MyTag);
}
void Set_get_mut_tag_existing_w_comp(void) {
install_test_abort();
ecs_world_t *world = ecs_mini();
ECS_COMPONENT(world, Position);
ECS_TAG(world, MyTag);
ecs_entity_t e = ecs_new(world, MyTag);
test_assert(e != 0);
test_assert( ecs_has(world, e, MyTag));
ecs_add(world, e, Position);
test_expect_abort();
ecs_get_mut_id(world, e, MyTag);
}
void Set_get_mut_tag_new_w_pair(void) {
install_test_abort();
ecs_world_t *world = ecs_mini();
ECS_COMPONENT(world, Position);
ECS_TAG(world, Pair);
ECS_TAG(world, MyTag);
ecs_entity_t e = ecs_new_w_id(world, ecs_pair(ecs_id(Position), Pair));
test_assert(e != 0);
test_expect_abort();
ecs_get_mut_id(world, e, MyTag);
}
void Set_get_mut_tag_existing_w_pair(void) {
install_test_abort();
ecs_world_t *world = ecs_mini();
ECS_COMPONENT(world, Position);
ECS_TAG(world, Pair);
ECS_TAG(world, MyTag);
ecs_entity_t e = ecs_new(world, MyTag);
test_assert(e != 0);
test_assert( ecs_has(world, e, MyTag));
ecs_add_pair(world, e, Pair, ecs_id(Position));
test_expect_abort();
ecs_get_mut_id(world, e, MyTag);
}
static bool is_invoked = false;
void OnSetPosition(ecs_iter_t *it) {
is_invoked = true;
}
void Set_modified_w_on_set(void) {
ecs_world_t *world = ecs_mini();
ECS_COMPONENT(world, Position);
ECS_OBSERVER(world, OnSetPosition, EcsOnSet, Position);
ecs_entity_t e = ecs_new(world, 0);
test_assert(e != 0);
Position *p = ecs_get_mut(world, e, Position);
test_assert(p != NULL);
test_assert( ecs_has(world, e, Position));
test_assert(p == ecs_get(world, e, Position));
test_assert(is_invoked == false);
ecs_modified(world, e, Position);
test_assert(is_invoked == true);
ecs_fini(world);
}
void Set_modified_no_component(void) {
install_test_abort();
ecs_world_t *world = ecs_mini();
ECS_COMPONENT(world, Position);
ECS_OBSERVER(world, OnSetPosition, EcsOnSet, Position);
ecs_entity_t e = ecs_new(world, 0);
test_assert(e != 0);
test_expect_abort();
/* This should trigger an assert */
ecs_modified(world, e, Position);
ecs_fini(world);
}
static ECS_COMPONENT_DECLARE(Position);
static ECS_COMPONENT_DECLARE(Velocity);
static
void OnAdd(ecs_iter_t *it) {
int i;
for (i = 0; i < it->count; i ++) {
ecs_add(it->world, it->entities[i], Velocity);
}
}
static
void OnAddRemove(ecs_iter_t *it) {
int i;
for (i = 0; i < it->count; i ++) {
ecs_remove(it->world, it->entities[i], Position);
}
}
void Set_get_mut_w_add_in_on_add(void) {
ecs_world_t *world = ecs_mini();
ECS_COMPONENT_DEFINE(world, Position);
ECS_COMPONENT_DEFINE(world, Velocity);
ECS_OBSERVER(world, OnAdd, EcsOnAdd, Position);
ecs_entity_t e = ecs_new_id(world);
Position *p = ecs_get_mut(world, e, Position);
test_assert(p != NULL);
p->x = 10;
p->y = 20;
const Position *pc = ecs_get(world, e, Position);
test_int(pc->x, 10);
test_int(pc->y, 20);
ecs_fini(world);
}
void Set_get_mut_w_remove_in_on_add(void) {
install_test_abort();
ecs_world_t *world = ecs_mini();
ECS_COMPONENT_DEFINE(world, Position);
ECS_OBSERVER(world, OnAddRemove, EcsOnAdd, Position);
ecs_entity_t e = ecs_new_id(world);
test_expect_abort();
/* get_mut is guaranteed to always return a valid pointer, so removing the
* component from the OnAdd trigger is not allowed */
ecs_get_mut(world, e, Position);
}
static
void OnAddRealloc(ecs_iter_t *it) {
ecs_entity_t *entities = it->ctx;
int i;
for (i = 0; i < 1000; i ++) {
ecs_set(it->world, entities[i], Velocity, {i, i * 2});
}
}
void Set_get_mut_w_realloc_in_on_add(void) {
ecs_world_t *world = ecs_mini();
ECS_COMPONENT_DEFINE(world, Position);
ECS_COMPONENT_DEFINE(world, Velocity);
ecs_entity_t *entities = ecs_os_malloc_n(ecs_entity_t, 1000);
for (int i = 0; i < 1000; i ++) {
entities[i] = ecs_new(world, Position);
}
ecs_observer_init(world, &(ecs_observer_desc_t){
.callback = OnAddRealloc,
.events = {EcsOnAdd},
.filter.terms[0].id = ecs_id(Position),
.ctx = entities
});
ecs_entity_t e = ecs_new(world, Velocity);
const Position *ptr = ecs_get_mut(world, e, Position);
test_assert(ptr == ecs_get(world, e, Position));
for (int i = 0; i < 1000; i ++) {
test_assert( ecs_has(world, entities[i], Velocity));
const Velocity *vptr = ecs_get(world, entities[i], Velocity);
test_assert(vptr != NULL);
// printf("e = {%f, %f}\n", vptr->x, vptr->y);
test_int(vptr->x, i);
test_int(vptr->y, i * 2);
test_assert(ecs_get_table(world, e) ==
ecs_get_table(world, entities[i]));
}
ecs_fini(world);
ecs_os_free(entities);
}
void Set_emplace(void) {
ecs_world_t *world = ecs_mini();
ECS_COMPONENT(world, Position);
ecs_entity_t e = ecs_new_id(world);
test_assert(e != 0);
Position *p = ecs_emplace(world, e, Position);
test_assert(p != NULL);
test_assert(ecs_has(world, e, Position));
test_assert(p == ecs_get(world, e, Position));
ecs_fini(world);
}
void Set_emplace_2(void) {
ecs_world_t *world = ecs_mini();
ECS_COMPONENT(world, Position);
ECS_COMPONENT(world, Velocity);
ecs_entity_t e = ecs_new_id(world);
test_assert(e != 0);
Position *p = ecs_emplace(world, e, Position);
test_assert(p != NULL);
test_assert(ecs_has(world, e, Position));
test_assert(p == ecs_get(world, e, Position));
Velocity *v = ecs_emplace(world, e, Velocity);
test_assert(v != NULL);
test_assert(ecs_has(world, e, Velocity));
test_assert(v == ecs_get(world, e, Velocity));
ecs_fini(world);
}
void Set_emplace_existing(void) {
install_test_abort();
ecs_world_t *world = ecs_mini();
ECS_COMPONENT(world, Position);
ecs_entity_t e = ecs_new(world, Position);
test_assert(ecs_has(world, e, Position));
test_assert(e != 0);
test_expect_abort();
ecs_emplace(world, e, Position);
}
void Set_emplace_w_move(void) {
ecs_world_t *world = ecs_mini();
ECS_COMPONENT(world, Position);
// Create entity with name, as name is component that is moved
ecs_entity_t e = ecs_set_name(world, 0, "Foo");
test_assert(e != 0);
test_str("Foo", ecs_get_name(world, e));
Position *p = ecs_emplace(world, e, Position);
test_assert(p != NULL);
test_assert(ecs_has(world, e, Position));
test_assert(p == ecs_get(world, e, Position));
test_str("Foo", ecs_get_name(world, e));
ecs_fini(world);
}
static
void OnAddMove(ecs_iter_t *it) {
int i;
for (i = 0; i < it->count; i ++) {
ecs_set(it->world, it->entities[i], Velocity, {1, 2});
}
}
void Set_emplace_w_observer_w_add(void) {
ecs_world_t *world = ecs_mini();
ECS_COMPONENT_DEFINE(world, Position);
ECS_COMPONENT_DEFINE(world, Velocity);
ecs_observer_init(world, &(ecs_observer_desc_t){
.callback = OnAddMove,
.events = {EcsOnAdd},
.filter.terms[0].id = ecs_id(Position)
});
ecs_entity_t e = ecs_new_id(world);
test_assert(e != 0);
Position *p = ecs_emplace(world, e, Position);
test_assert(p != NULL);
p->x = 10;
p->y = 20;
test_assert(ecs_has(world, e, Position));
{
const Position *pc = ecs_get(world, e, Position);
test_assert(p == pc);
test_int(pc->x, 10);
test_int(pc->y, 20);
const Velocity *vc = ecs_get(world, e, Velocity);
test_assert(vc != NULL);
test_int(vc->x, 1);
test_int(vc->y, 2);
}
ecs_fini(world);
}

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,91 @@
#include <api.h>
void Singleton_add_singleton(void) {
ecs_world_t *world = ecs_mini();
ECS_TAG(world, TagA);
test_assert(!ecs_has(world, TagA, TagA));
ecs_singleton_add(world, TagA);
test_assert(ecs_has(world, TagA, TagA));
ecs_fini(world);
}
void Singleton_remove_singleton(void) {
ecs_world_t *world = ecs_mini();
ECS_TAG(world, TagA);
test_assert(!ecs_has(world, TagA, TagA));
ecs_singleton_add(world, TagA);
test_assert(ecs_has(world, TagA, TagA));
ecs_singleton_remove(world, TagA);
test_assert(!ecs_has(world, TagA, TagA));
ecs_fini(world);
}
void Singleton_set_get_singleton(void) {
ecs_world_t *world = ecs_mini();
ECS_COMPONENT(world, Position);
ecs_singleton_set(world, Position, {10, 20});
const Position *p = ecs_singleton_get(world, Position);
test_assert(p != NULL);
test_int(p->x, 10);
test_int(p->y, 20);
ecs_fini(world);
}
void Singleton_get_mut_singleton(void) {
ecs_world_t *world = ecs_mini();
ECS_COMPONENT(world, Position);
Position *p_mut = ecs_singleton_get_mut(world, Position);
p_mut->x = 10;
p_mut->y = 20;
const Position *p = ecs_singleton_get(world, Position);
test_assert(p != NULL);
test_int(p->x, 10);
test_int(p->y, 20);
ecs_fini(world);
}
static
void IncSingleton(ecs_iter_t *it) {
Position *p = ecs_field(it, Position, 1);
p->x ++;
p->y ++;
}
void Singleton_singleton_system(void) {
ecs_world_t *world = ecs_init();
ECS_COMPONENT(world, Position);
ECS_SYSTEM(world, IncSingleton, EcsOnUpdate, Position($));
ecs_singleton_set(world, Position, {10, 20});
ecs_progress(world, 0);
const Position *p = ecs_singleton_get(world, Position);
test_assert(p != NULL);
test_int(p->x, 11);
test_int(p->y, 21);
ecs_fini(world);
}

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,65 @@
#include <api.h>
#include "../../../src/private_api.h"
void StackAlloc_init_fini(void) {
ecs_world_t *world = ecs_mini();
ecs_stack_t stack = {0};
flecs_stack_init(&stack);
test_int(stack.tail_page->sp, 0);
test_assert(stack.tail_page == &stack.first);
flecs_stack_fini(&stack);
ecs_fini(world);
}
/// @brief Utililty for creating a mock allocation on the stack allocator
/// @param stack Stack to use
/// @param allocSizes Array of sizes to alloc. All of alignment 1. Ends with a size of 0.
/// @return cursor to start of allocations
static
ecs_stack_cursor_t* init_some_object(ecs_stack_t* stack, int32_t* allocSizes) {
ecs_stack_cursor_t *cursor = flecs_stack_get_cursor(stack);
while (*allocSizes > 0)
{
flecs_stack_calloc(stack, *allocSizes++, 1);
}
return cursor;
}
void StackAlloc_multiple_overlapping_cursors(void) {
ecs_world_t *world = ecs_mini();
ecs_stack_t stack = {0};
flecs_stack_init(&stack);
ecs_stack_cursor_t *cursor1 = init_some_object(&stack, (int32_t[]){64, 64, 0});
int16_t spAfter1 = stack.tail_page->sp;
ecs_stack_cursor_t *cursor2 = init_some_object(&stack, (int32_t[]){64, 64, 0});
ecs_stack_cursor_t *cursor3 = init_some_object(&stack, (int32_t[]){64, 64, 0});
int16_t spAfter3 = stack.tail_page->sp;
ecs_stack_cursor_t *cursor4 = init_some_object(&stack, (int32_t[]){64, 64, 0});
int16_t spAfter4 = stack.tail_page->sp;
// [] == in use, {} == free
// [1] [2] [3] [4]
flecs_stack_restore_cursor(&stack, cursor2);
// [1] {2} [3] [4]
test_int(stack.tail_page->sp, spAfter4);
flecs_stack_restore_cursor(&stack, cursor4);
// [1] {2} [3]
test_int(stack.tail_page->sp, spAfter3);
flecs_stack_restore_cursor(&stack, cursor3);
// [1]
test_int(stack.tail_page->sp, spAfter1);
flecs_stack_restore_cursor(&stack, cursor1);
// Empty
test_int(stack.tail_page->sp, 0);
flecs_stack_fini(&stack);
ecs_fini(world);
}

View File

@@ -0,0 +1,339 @@
#include <api.h>
#include <stdlib.h>
void Stresstests_setup(void) {
ecs_log_set_level(-3);
}
static
void add_random(
ecs_world_t *world,
ecs_entity_t entity,
ecs_entity_t component)
{
if (rand() % 2) {
if (!entity) {
entity = ecs_new_w_id(world, component);
} else {
ecs_add_id(world, entity, component);
}
}
}
static
void set_random(
ecs_world_t *world,
ecs_entity_t entity,
ecs_entity_t component,
void *ptr,
void *expect,
int32_t size)
{
if (rand() % 2) {
ecs_set_id(world, entity, component, size, ptr);
}
}
static
void Delete_above_1000(ecs_iter_t *it) {
int i;
for (i = 0; i < it->count; i ++) {
if ((i + it->frame_offset) > 1000) {
ecs_delete(it->world, it->entities[i]);
}
}
}
static
void Add_random(ecs_iter_t *it) {
IterData *ctx = ecs_get_ctx(it->world);
int i;
for (i = 0; i < it->count; i ++) {
add_random(it->world, 0, ctx->component);
add_random(it->world, it->entities[i], ctx->component_2);
add_random(it->world, it->entities[i], ctx->component_3);
}
}
static
void Set_velocity_callback(ecs_iter_t *it) {
Velocity *v = ecs_field(it, Velocity, 1);
int i;
for (i = 0; i < it->count; i ++) {
v->x ++;
v->y ++;
}
}
static
void Set_random(ecs_iter_t *it) {
IterData *ctx = ecs_get_ctx(it->world);
int i;
for (i = 0; i < it->count; i ++) {
Position pos = {10, 20};
set_random(it->world, 0, ctx->component, &pos, &pos, sizeof(Position));
Velocity vel = {30, 40};
Velocity vel_expect = {31, 41};
set_random(it->world, it->entities[i], ctx->component_2, &vel, &vel_expect,
sizeof(Velocity));
Rotation rot = {50};
set_random(it->world, it->entities[i], ctx->component_3, &rot, &rot,
sizeof(Rotation));
}
}
static
void create_delete_entity_random_components_staged(
int32_t threads)
{
test_quarantine("16 Jan 2023");
return;
ecs_world_t *world = ecs_init();
ECS_COMPONENT(world, Position);
ECS_COMPONENT(world, Velocity);
ECS_COMPONENT(world, Rotation);
ECS_PREFAB(world, Type, Position, Velocity);
ECS_SYSTEM(world, Add_random, EcsOnUpdate, Position);
ECS_SYSTEM(world, Delete_above_1000, EcsPostUpdate, Position);
ecs_system_init(world, &(ecs_system_desc_t){
.entity = Add_random,
.multi_threaded = true
});
ecs_system_init(world, &(ecs_system_desc_t){
.entity = Delete_above_1000,
.multi_threaded = true
});
IterData ctx = {.component = ecs_id(Position), .component_2 = ecs_id(Velocity), .component_3 = ecs_id(Rotation)};
ecs_set_ctx(world, &ctx, NULL);
ecs_bulk_new(world, Position, 500);
bulk_new_w_type(world, Type, 500);
if (threads) {
ecs_set_threads(world, threads);
}
uint64_t i;
for (i = 0; i < 100; i ++) {
ecs_progress(world, 1);
}
test_assert(true);
ecs_fini(world);
}
static
void set_entity_random_components(
int32_t threads)
{
test_quarantine("16 Jan 2023");
return;
ecs_world_t *world = ecs_init();
ECS_COMPONENT(world, Position);
ECS_COMPONENT(world, Velocity);
ECS_COMPONENT(world, Rotation);
ECS_PREFAB(world, Type, Position, Velocity);
ECS_SYSTEM(world, Set_random, EcsOnUpdate, Position);
ECS_SYSTEM(world, Set_velocity_callback, EcsOnSet, Velocity);
ECS_SYSTEM(world, Delete_above_1000, EcsPostUpdate, Position);
ecs_system_init(world, &(ecs_system_desc_t){
.entity = Set_random,
.multi_threaded = true
});
ecs_system_init(world, &(ecs_system_desc_t){
.entity = Delete_above_1000,
.multi_threaded = true
});
IterData ctx = {.component = ecs_id(Position), .component_2 = ecs_id(Velocity), .component_3 = ecs_id(Rotation)};
ecs_set_ctx(world, &ctx, NULL);
const ecs_entity_t *ids = ecs_bulk_new(world, Position, 5);
test_assert(ids != NULL);
ids = bulk_new_w_type(world, Type, 5);
test_assert(ids != NULL);
if (threads) {
ecs_set_threads(world, threads);
}
int i;
for (i = 0; i < 100; i ++) {
ecs_progress(world, 1);
}
ecs_fini(world);
}
void Stresstests_create_delete_entity_random_components(void) {
ecs_world_t *world = ecs_init();
ECS_COMPONENT(world, Position);
ECS_COMPONENT(world, Velocity);
ECS_COMPONENT(world, Rotation);
const ecs_entity_t *ids = ecs_bulk_new(world, 0, 1000);
test_assert(ids != NULL);
int i;
for (i = 0; i < 1000; i ++) {
add_random(world, ids[i], ecs_id(Position));
add_random(world, ids[i], ecs_id(Velocity));
add_random(world, ids[i], ecs_id(Rotation));
}
ecs_fini(world);
}
void Stresstests_set_entity_random_components(void) {
ecs_world_t *world = ecs_init();
ECS_COMPONENT(world, Position);
ECS_COMPONENT(world, Velocity);
ECS_COMPONENT(world, Rotation);
ECS_SYSTEM(world, Set_velocity_callback, EcsOnSet, Velocity);
const ecs_entity_t *ids = ecs_bulk_new(world, 0, 1000);
test_assert(ids != NULL);
int i;
for (i = 0; i < 1000; i ++) {
Position pos = {10, 20};
set_random(world, ids[i], ecs_id(Position), &pos, &pos, sizeof(Position));
Velocity vel = {30, 40};
Velocity vel_expect = {31, 41};
set_random(world, ids[i], ecs_id(Velocity), &vel, &vel_expect, sizeof(Velocity));
Rotation rot = {50};
set_random(world, ids[i], ecs_id(Rotation), &rot, &rot, sizeof(Rotation));
}
ecs_fini(world);
}
void Stresstests_create_delete_entity_random_components_staged(void) {
create_delete_entity_random_components_staged(0);
}
void Stresstests_set_entity_random_components_staged(void) {
set_entity_random_components(0);
}
void Stresstests_create_delete_entity_random_components_2_threads(void) {
create_delete_entity_random_components_staged(2);
}
void Stresstests_set_entity_random_components_2_threads(void) {
set_entity_random_components(2);
}
void Stresstests_create_delete_entity_random_components_6_threads(void) {
create_delete_entity_random_components_staged(6);
}
void Stresstests_set_entity_random_components_6_threads(void) {
set_entity_random_components(6);
}
void Stresstests_create_delete_entity_random_components_12_threads(void) {
create_delete_entity_random_components_staged(12);
}
void Stresstests_set_entity_random_components_12_threads(void) {
set_entity_random_components(12);
}
void Stresstests_create_2m_entities_1_comp(void) {
ecs_world_t *world = ecs_init();
ECS_COMPONENT(world, Position);
int32_t i;
for (i = 0; i < 2000 * 1000; i ++) {
ecs_entity_t e = ecs_new(world, Position);
test_assert(e != 0);
test_assert(ecs_has(world, e, Position));
}
ecs_fini(world);
}
void Stresstests_create_2m_entities_bulk_1_comp(void) {
ecs_world_t *world = ecs_init();
ECS_COMPONENT(world, Position);
const ecs_entity_t *ids = ecs_bulk_new(world, Position, 2000 * 1000);
test_assert(ids != NULL);
int32_t i;
for (i = 0; i < 2000 * 1000; i ++) {
test_assert(ecs_has(world, ids[i], Position));
}
ecs_fini(world);
}
void Stresstests_add_1k_tags(void) {
ecs_world_t *world = ecs_init();
ecs_entity_t e = ecs_new(world, 0);
int i;
for (i = 0; i < 1000; i ++) {
ecs_add_id(world, e, i + 1000);
test_assert(ecs_has_id(world, e, i + 1000));
}
const ecs_type_t *type = ecs_get_type(world, e);
test_assert(type != NULL);
test_int(type->count, 1000);
ecs_fini(world);
}
void Stresstests_create_1m_set_two_components(void) {
ecs_world_t *world = ecs_init();
ECS_COMPONENT(world, Position);
ECS_COMPONENT(world, Velocity);
ecs_entity_t e = ecs_new(world, 0);
ecs_entity_t i, j;
for (i = e; i < 1000000 + e; i ++) {
ecs_ensure(world, i);
ecs_set(world, i, Position, {10, 20});
}
for (j = e; j < 1000000 + e; j ++) {
test_assert(ecs_get_type(world, j) != NULL);
}
for (i = e; i < e + 1000000 + e; i ++) {
ecs_ensure(world, i);
ecs_set(world, i, Velocity, {1, 2});
}
ecs_fini(world);
}

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,379 @@
#include <api.h>
void Table_get_index(void) {
ecs_world_t *world = ecs_mini();
ECS_COMPONENT(world, Position);
ECS_COMPONENT(world, Velocity);
ecs_entity_t e = ecs_new_id(world);
ecs_set(world, e, Position, {10, 20});
ecs_set(world, e, Velocity, {10, 20});
ecs_table_t *table = ecs_get_table(world, e);
test_assert(table != NULL);
test_int(ecs_table_get_type_index(world, table, ecs_id(Position)), 0);
test_int(ecs_table_get_type_index(world, table, ecs_id(Velocity)), 1);
ecs_fini(world);
}
void Table_get_index_not_in_table(void) {
ecs_world_t *world = ecs_mini();
ECS_COMPONENT(world, Position);
ECS_COMPONENT(world, Velocity);
ECS_COMPONENT(world, Mass);
ecs_entity_t e = ecs_new_id(world);
ecs_set(world, e, Position, {10, 20});
ecs_set(world, e, Velocity, {10, 20});
ecs_table_t *table = ecs_get_table(world, e);
test_assert(table != NULL);
test_int(ecs_table_get_type_index(world, table, ecs_id(Position)), 0);
test_int(ecs_table_get_type_index(world, table, ecs_id(Velocity)), 1);
test_int(ecs_table_get_type_index(world, table, ecs_id(Mass)), -1);
ecs_fini(world);
}
void Table_get_column(void) {
ecs_world_t *world = ecs_mini();
ECS_COMPONENT(world, Position);
ECS_COMPONENT(world, Velocity);
ecs_entity_t e1 = ecs_new_id(world);
ecs_set(world, e1, Position, {10, 20});
ecs_set(world, e1, Velocity, {1, 2});
ecs_entity_t e2 = ecs_new_id(world);
ecs_set(world, e2, Position, {20, 30});
ecs_set(world, e2, Velocity, {2, 3});
ecs_table_t *table = ecs_get_table(world, e1);
test_assert(table != NULL);
int32_t pos_id = ecs_table_get_column_index(world, table, ecs_id(Position));
int32_t vel_id = ecs_table_get_column_index(world, table, ecs_id(Velocity));
Position *p = ecs_table_get_column(table, pos_id, 0);
test_assert(p != NULL);
test_int(p[0].x, 10);
test_int(p[0].y, 20);
test_int(p[1].x, 20);
test_int(p[1].y, 30);
Velocity *v = ecs_table_get_column(table, vel_id, 0);
test_assert(v != NULL);
test_int(v[0].x, 1);
test_int(v[0].y, 2);
test_int(v[1].x, 2);
test_int(v[1].y, 3);
ecs_fini(world);
}
void Table_get_column_for_tag(void) {
install_test_abort();
ecs_world_t *world = ecs_mini();
ECS_COMPONENT(world, Position);
ECS_TAG(world, Tag);
ecs_entity_t e1 = ecs_new_id(world);
ecs_set(world, e1, Position, {10, 20});
ecs_add(world, e1, Tag);
ecs_table_t *table = ecs_get_table(world, e1);
test_assert(table != NULL);
test_expect_abort();
int32_t tag_id = ecs_table_get_type_index(world, table, Tag);
test_expect_abort();
ecs_table_get_column(table, tag_id, 0);
}
void Table_get_column_for_component_after_tag(void) {
ecs_world_t *world = ecs_mini();
ECS_COMPONENT(world, Position);
ecs_entity_t tag_w_low_id = ecs_entity(world, {
.use_low_id = true
});
ECS_COMPONENT(world, Velocity);
ecs_entity_t e1 = ecs_new_id(world);
ecs_set(world, e1, Position, {10, 20});
ecs_set(world, e1, Velocity, {1, 2});
ecs_add_id(world, e1, tag_w_low_id);
ecs_entity_t e2 = ecs_new_id(world);
ecs_set(world, e2, Position, {20, 30});
ecs_set(world, e2, Velocity, {2, 3});
ecs_add_id(world, e2, tag_w_low_id);
ecs_table_t *table = ecs_get_table(world, e1);
test_assert(table != NULL);
int32_t pos_id = ecs_table_get_column_index(world, table, ecs_id(Position));
int32_t vel_id = ecs_table_get_column_index(world, table, ecs_id(Velocity));
test_assert(pos_id != -1);
test_assert(vel_id != -1);
Position *p = ecs_table_get_column(table, pos_id, 0);
test_assert(p != NULL);
test_int(p[0].x, 10);
test_int(p[0].y, 20);
test_int(p[1].x, 20);
test_int(p[1].y, 30);
Velocity *v = ecs_table_get_column(table, vel_id, 0);
test_assert(v != NULL);
test_int(v[0].x, 1);
test_int(v[0].y, 2);
test_int(v[1].x, 2);
test_int(v[1].y, 3);
ecs_fini(world);
}
void Table_get_column_w_offset(void) {
ecs_world_t *world = ecs_mini();
ECS_COMPONENT(world, Position);
ECS_COMPONENT(world, Velocity);
ecs_entity_t e1 = ecs_new_id(world);
ecs_set(world, e1, Position, {10, 20});
ecs_set(world, e1, Velocity, {1, 2});
ecs_entity_t e2 = ecs_new_id(world);
ecs_set(world, e2, Position, {20, 30});
ecs_set(world, e2, Velocity, {2, 3});
ecs_table_t *table = ecs_get_table(world, e1);
test_assert(table != NULL);
int32_t pos_id = ecs_table_get_column_index(world, table, ecs_id(Position));
int32_t vel_id = ecs_table_get_column_index(world, table, ecs_id(Velocity));
Position *p = ecs_table_get_column(table, pos_id, 1);
test_assert(p != NULL);
test_int(p[0].x, 20);
test_int(p[0].y, 30);
Velocity *v = ecs_table_get_column(table, vel_id, 1);
test_assert(v != NULL);
test_int(v[0].x, 2);
test_int(v[0].y, 3);
ecs_fini(world);
}
void Table_get_id(void) {
ecs_world_t *world = ecs_mini();
ECS_COMPONENT(world, Position);
ECS_COMPONENT(world, Velocity);
ecs_entity_t e1 = ecs_new_id(world);
ecs_set(world, e1, Position, {10, 20});
ecs_set(world, e1, Velocity, {1, 2});
ecs_entity_t e2 = ecs_new_id(world);
ecs_set(world, e2, Position, {20, 30});
ecs_set(world, e2, Velocity, {2, 3});
ecs_table_t *table = ecs_get_table(world, e1);
test_assert(table != NULL);
Position *p = ecs_table_get_id(world, table, ecs_id(Position), 0);
test_int(p[0].x, 10);
test_int(p[0].y, 20);
test_int(p[1].x, 20);
test_int(p[1].y, 30);
Velocity *v = ecs_table_get_id(world, table, ecs_id(Velocity), 0);
test_int(v[0].x, 1);
test_int(v[0].y, 2);
test_int(v[1].x, 2);
test_int(v[1].y, 3);
ecs_fini(world);
}
void Table_get_component(void) {
ecs_world_t *world = ecs_mini();
ECS_COMPONENT(world, Position);
ECS_COMPONENT(world, Velocity);
ecs_entity_t e1 = ecs_new_id(world);
ecs_set(world, e1, Position, {10, 20});
ecs_set(world, e1, Velocity, {1, 2});
ecs_entity_t e2 = ecs_new_id(world);
ecs_set(world, e2, Position, {20, 30});
ecs_set(world, e2, Velocity, {2, 3});
ecs_table_t *table = ecs_get_table(world, e1);
test_assert(table != NULL);
Position *p = ecs_table_get(world, table, Position, 0);
test_int(p[0].x, 10);
test_int(p[0].y, 20);
test_int(p[1].x, 20);
test_int(p[1].y, 30);
Velocity *v = ecs_table_get(world, table, Velocity, 0);
test_int(v[0].x, 1);
test_int(v[0].y, 2);
test_int(v[1].x, 2);
test_int(v[1].y, 3);
ecs_fini(world);
}
void Table_get_pair(void) {
ecs_world_t *world = ecs_mini();
ECS_COMPONENT(world, Position);
ECS_COMPONENT(world, Velocity);
ECS_TAG(world, Tgt);
ecs_entity_t e1 = ecs_new_id(world);
ecs_set_pair(world, e1, Position, Tgt, {10, 20});
ecs_set_pair(world, e1, Velocity, Tgt, {1, 2});
ecs_entity_t e2 = ecs_new_id(world);
ecs_set_pair(world, e2, Position, Tgt, {20, 30});
ecs_set_pair(world, e2, Velocity, Tgt, {2, 3});
ecs_table_t *table = ecs_get_table(world, e1);
test_assert(table != NULL);
Position *p = ecs_table_get_pair(world, table, Position, Tgt, 0);
test_int(p[0].x, 10);
test_int(p[0].y, 20);
test_int(p[1].x, 20);
test_int(p[1].y, 30);
Velocity *v = ecs_table_get_pair(world, table, Velocity, Tgt, 0);
test_int(v[0].x, 1);
test_int(v[0].y, 2);
test_int(v[1].x, 2);
test_int(v[1].y, 3);
ecs_fini(world);
}
void Table_get_from_stage(void) {
ecs_world_t *world = ecs_mini();
ECS_COMPONENT(world, Position);
ECS_COMPONENT(world, Velocity);
ecs_entity_t e1 = ecs_new_id(world);
ecs_set(world, e1, Position, {10, 20});
ecs_set(world, e1, Velocity, {1, 2});
ecs_entity_t e2 = ecs_new_id(world);
ecs_set(world, e2, Position, {20, 30});
ecs_set(world, e2, Velocity, {2, 3});
ecs_table_t *table = ecs_get_table(world, e1);
test_assert(table != NULL);
ecs_world_t *stage = ecs_get_stage(world, 0);
test_assert(stage != NULL);
test_assert(stage != world);
Position *p = ecs_table_get(stage, table, Position, 0);
test_int(p[0].x, 10);
test_int(p[0].y, 20);
test_int(p[1].x, 20);
test_int(p[1].y, 30);
Velocity *v = ecs_table_get(stage, table, Velocity, 0);
test_int(v[0].x, 1);
test_int(v[0].y, 2);
test_int(v[1].x, 2);
test_int(v[1].y, 3);
ecs_fini(world);
}
void Table_get_depth(void) {
ecs_world_t *world = ecs_mini();
ecs_entity_t e1 = ecs_new_id(world);
ecs_entity_t e2 = ecs_new_w_pair(world, EcsChildOf, e1);
ecs_entity_t e3 = ecs_new_w_pair(world, EcsChildOf, e2);
ecs_entity_t e4 = ecs_new_w_pair(world, EcsChildOf, e3);
test_int(1, ecs_table_get_depth(world, ecs_get_table(world, e2), EcsChildOf));
test_int(2, ecs_table_get_depth(world, ecs_get_table(world, e3), EcsChildOf));
test_int(3, ecs_table_get_depth(world, ecs_get_table(world, e4), EcsChildOf));
ecs_fini(world);
}
void Table_get_depth_non_acyclic(void) {
install_test_abort();
ecs_world_t *world = ecs_mini();
ECS_TAG(world, Rel);
ECS_TAG(world, Tgt);
ecs_entity_t e1 = ecs_new_w_pair(world, Rel, Tgt);
test_expect_abort();
ecs_table_get_depth(world, ecs_get_table(world, e1), Rel);
}
void Table_get_depth_2_paths(void) {
ecs_world_t *world = ecs_mini();
ecs_entity_t e1 = ecs_new_id(world);
ecs_entity_t e2 = ecs_new_w_pair(world, EcsIsA, e1);
ecs_entity_t e3 = ecs_new_w_pair(world, EcsIsA, e2);
ecs_entity_t e4 = ecs_new_w_pair(world, EcsIsA, e2);
ecs_add_pair(world, e4, EcsIsA, e3);
test_int(1, ecs_table_get_depth(world, ecs_get_table(world, e2), EcsIsA));
test_int(2, ecs_table_get_depth(world, ecs_get_table(world, e3), EcsIsA));
test_int(3, ecs_table_get_depth(world, ecs_get_table(world, e4), EcsIsA));
ecs_fini(world);
}
void Table_get_column_size(void) {
ecs_world_t *world = ecs_mini();
ECS_COMPONENT(world, Position);
ECS_TAG(world, Tag);
ecs_entity_t ecs_id(Mass) = ecs_component(world, {
.entity = ecs_new_id(world),
.type.size = 4,
.type.alignment = 4
});
ecs_entity_t e1 = ecs_new_id(world);
ecs_set(world, e1, Position, {10, 20});
ecs_add(world, e1, Tag);
ecs_set(world, e1, Mass, {1});
ecs_table_t *table = ecs_get_table(world, e1);
test_assert(table != NULL);
test_uint(8, ecs_table_get_column_size(table, 0));
test_uint(4, ecs_table_get_column_size(table, 1));
ecs_fini(world);
}

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,420 @@
#include <api.h>
void Deinit(ecs_iter_t *it) {
Position *p = ecs_field(it, Position, 1);
Velocity *v = NULL;
if (it->field_count >= 2) {
v = ecs_field(it, Velocity, 2);
}
probe_iter(it);
/* Write to validate columns point to valid memory */
int i;
for (i = 0; i < it->count; i ++) {
p[i].x = 0;
p[i].y = 0;
if (v) {
v[i].x = 0;
v[i].y = 0;
}
}
}
static
void Remove_from_current(ecs_iter_t *it) {
IterData *ctx = ecs_get_ctx(it->world);
int i;
for (i = 0; i < it->count; i ++) {
ecs_entity_t e = it->entities[i];
if (ctx->component) {
ecs_remove_id(it->world, e, ctx->component);
}
if (ctx->component_2) {
ecs_remove_id(it->world, e, ctx->component_2);
}
ctx->entity_count ++;
}
}
void TriggerOnRemove_remove(void) {
ecs_world_t *world = ecs_mini();
ECS_COMPONENT(world, Position);
ECS_OBSERVER(world, Deinit, EcsOnRemove, Position);
Probe ctx = {0};
ecs_set_ctx(world, &ctx, NULL);
ecs_entity_t e = ecs_new(world, Position);
test_assert(e != 0);
test_int(ctx.count, 0);
ecs_remove(world, e, Position);
test_int(ctx.count, 1);
test_int(ctx.term_count, 1);
test_null(ctx.param);
test_int(ctx.e[0], e);
test_int(ctx.c[0][0], ecs_id(Position));
test_int(ctx.s[0][0], 0);
ecs_fini(world);
}
void TriggerOnRemove_remove_no_match(void) {
ecs_world_t *world = ecs_mini();
ECS_COMPONENT(world, Position);
ECS_COMPONENT(world, Velocity);
ECS_OBSERVER(world, Deinit, EcsOnRemove, Position);
Probe ctx = {0};
ecs_set_ctx(world, &ctx, NULL);
ecs_entity_t e = ecs_new(world, Position);
test_assert(e != 0);
test_int(ctx.count, 0);
ecs_remove(world, e, Velocity);
test_int(ctx.count, 0);
ecs_fini(world);
}
void TriggerOnRemove_delete(void) {
ecs_world_t *world = ecs_mini();
ECS_COMPONENT(world, Position);
ECS_OBSERVER(world, Deinit, EcsOnRemove, Position);
Probe ctx = {0};
ecs_set_ctx(world, &ctx, NULL);
ecs_entity_t e = ecs_new(world, Position);
test_assert(e != 0);
test_int(ctx.count, 0);
ecs_delete(world, e);
test_int(ctx.count, 1);
test_int(ctx.term_count, 1);
test_null(ctx.param);
test_int(ctx.e[0], e);
test_int(ctx.c[0][0], ecs_id(Position));
test_int(ctx.s[0][0], 0);
ecs_fini(world);
}
void TriggerOnRemove_delete_no_match(void) {
ecs_world_t *world = ecs_mini();
ECS_COMPONENT(world, Position);
ECS_COMPONENT(world, Velocity);
ECS_OBSERVER(world, Deinit, EcsOnRemove, Position);
Probe ctx = {0};
ecs_set_ctx(world, &ctx, NULL);
ecs_entity_t e = ecs_new(world, Velocity);
test_assert(e != 0);
test_int(ctx.count, 0);
ecs_delete(world, e);
test_int(ctx.count, 0);
ecs_fini(world);
}
static Position old_position = {0};
static
void RemovePosition(ecs_iter_t *it) {
Position *p = ecs_field(it, Position, 1);
test_assert(it->count == 1);
old_position = p[0];
}
void TriggerOnRemove_remove_watched(void) {
ecs_world_t *world = ecs_mini();
ECS_COMPONENT(world, Position);
ECS_OBSERVER(world, RemovePosition, EcsOnRemove, Position);
ecs_entity_t e = ecs_set(world, 0, Position, {10, 20});
test_assert(e != 0);
/* Make parent entity watched */
ecs_new_w_pair(world, EcsChildOf, e);
ecs_remove(world, e, Position);
test_int(old_position.x, 10);
test_int(old_position.y, 20);
ecs_fini(world);
}
void TriggerOnRemove_delete_watched(void) {
ecs_world_t *world = ecs_mini();
ECS_COMPONENT(world, Position);
ECS_OBSERVER(world, RemovePosition, EcsOnRemove, Position);
ecs_entity_t e = ecs_set(world, 0, Position, {10, 20});
test_assert(e != 0);
/* Make parent entity watched */
ecs_new_w_pair(world, EcsChildOf, e);
ecs_delete(world, e);
test_int(old_position.x, 10);
test_int(old_position.y, 20);
ecs_fini(world);
}
static bool dummy_called = false;
static
void Dummy(ecs_iter_t *it) {
dummy_called = true;
}
void TriggerOnRemove_on_remove_in_on_update(void) {
ecs_world_t *world = ecs_init();
ECS_COMPONENT(world, Position);
ECS_COMPONENT(world, Velocity);
ECS_SYSTEM(world, Remove_from_current, EcsOnUpdate, Position);
ECS_OBSERVER(world, Dummy, EcsOnRemove, Velocity);
IterData ctx = {.component = ecs_id(Velocity)};
ecs_set_ctx(world, &ctx, NULL);
ECS_ENTITY(world, e1, Position, Velocity);
ECS_ENTITY(world, e2, Position, Velocity);
ECS_ENTITY(world, e3, Position, Velocity);
ecs_progress(world, 1);
test_assert( ecs_has(world, e1, Position));
test_assert( ecs_has(world, e2, Position));
test_assert( ecs_has(world, e3, Position));
test_assert( !ecs_has(world, e1, Velocity));
test_assert( !ecs_has(world, e2, Velocity));
test_assert( !ecs_has(world, e3, Velocity));
test_assert(dummy_called);
ecs_fini(world);
}
static int dummy_dtor_invoked = 0;
typedef struct DummyComp {
int value;
} DummyComp;
static
void RemoveDummyComp(ecs_iter_t *it) {
int i;
for (i = 0; i < it->count; i ++) {
test_assert(ecs_is_valid(it->world, it->entities[i]));
test_assert(ecs_is_alive(it->world, it->entities[i]));
}
dummy_dtor_invoked ++;
}
void TriggerOnRemove_valid_entity_after_delete(void) {
ecs_world_t *world = ecs_mini();
ECS_COMPONENT(world, DummyComp);
ECS_OBSERVER(world, RemoveDummyComp, EcsOnRemove, DummyComp);
ecs_entity_t e = ecs_new(world, DummyComp);
test_assert(e != 0);
ecs_delete(world, e);
test_assert(!ecs_is_valid(world, e));
test_assert(!ecs_is_alive(world, e));
test_int(dummy_dtor_invoked, 1);
ecs_fini(world);
}
void TriggerOnRemove_remove_after_delete_trigger(void) {
ecs_world_t *world = ecs_mini();
ECS_COMPONENT(world, Position);
ecs_entity_t trigger = ecs_observer_init(world, &(ecs_observer_desc_t){
.filter.terms[0].id = ecs_id(Position),
.events = {EcsOnRemove},
.callback = Dummy
});
ecs_entity_t e1 = ecs_new(world, Position);
test_assert(e1 != 0);
test_assert(ecs_has(world, e1, Position));
test_int(dummy_called, 0);
ecs_remove(world, e1, Position);
test_int(dummy_called, 1);
dummy_called = 0;
ecs_delete(world, trigger);
test_int(dummy_called, 0);
ecs_entity_t e2 = ecs_new(world, Position);
test_assert(e2 != 0);
test_assert(ecs_has(world, e2, Position));
test_int(dummy_called, 0);
ecs_remove(world, e2, Position);
test_int(dummy_called, 0);
ecs_fini(world);
}
void TriggerOnRemove_remove_after_delete_wildcard_id_trigger(void) {
ecs_world_t *world = ecs_mini();
ECS_COMPONENT(world, Position);
ecs_entity_t trigger = ecs_observer_init(world, &(ecs_observer_desc_t){
.filter.terms[0].id = EcsWildcard,
.events = {EcsOnRemove},
.callback = Dummy
});
ecs_entity_t e1 = ecs_new(world, Position);
test_assert(e1 != 0);
test_assert(ecs_has(world, e1, Position));
test_int(dummy_called, 0);
ecs_remove(world, e1, Position);
test_int(dummy_called, 1);
dummy_called = 0;
ecs_delete(world, trigger);
test_int(dummy_called, 1);
dummy_called = 0;
ecs_entity_t e2 = ecs_new(world, Position);
test_assert(e2 != 0);
test_assert(ecs_has(world, e2, Position));
test_int(dummy_called, 0);
ecs_remove(world, e2, Position);
test_int(dummy_called, 0);
ecs_fini(world);
}
typedef struct on_remove_has_tag_t {
ecs_entity_t ent;
ecs_entity_t tag;
} on_remove_has_tag_t;
static
void OnRemoveHasTag(ecs_iter_t *it) {
on_remove_has_tag_t *ctx = it->ctx;
test_assert(ctx != NULL);
test_int(it->count, 1);
test_assert(it->entities[0] == ctx->ent);
test_assert(ecs_field_id(it, 1) == ctx->tag);
test_bool(ecs_has_id(it->world, ctx->ent, ctx->tag), true);
dummy_called = true;
}
void TriggerOnRemove_has_removed_tag_trigger_1_tag(void) {
ecs_world_t *world = ecs_mini();
ECS_TAG(world, Tag);
ecs_entity_t e = ecs_new(world, Tag);
test_assert(e != 0);
test_assert(ecs_has(world, e, Tag));
on_remove_has_tag_t ctx = {
.ent = e,
.tag = Tag
};
ecs_observer_init(world, &(ecs_observer_desc_t){
.filter.terms[0].id = Tag,
.events = {EcsOnRemove},
.callback = OnRemoveHasTag,
.ctx = &ctx
});
ecs_remove(world, e, Tag);
test_int(dummy_called, 1);
ecs_fini(world);
}
void TriggerOnRemove_has_removed_tag_trigger_2_tags(void) {
ecs_world_t *world = ecs_mini();
ECS_TAG(world, TagA);
ECS_TAG(world, TagB);
ecs_entity_t e = ecs_new(world, TagA);
test_assert(e != 0);
test_assert(ecs_has(world, e, TagA));
ecs_add(world, e, TagB);
test_assert(ecs_has(world, e, TagB));
on_remove_has_tag_t ctx = {
.ent = e,
.tag = TagA
};
ecs_observer_init(world, &(ecs_observer_desc_t){
.filter.terms[0].id = TagA,
.events = {EcsOnRemove},
.callback = OnRemoveHasTag,
.ctx = &ctx
});
ecs_remove(world, e, TagA);
test_int(dummy_called, 1);
ecs_fini(world);
}

View File

@@ -0,0 +1,679 @@
#include <api.h>
static
void Trigger(ecs_iter_t *it) {
probe_iter(it);
}
static
void OnSet(ecs_iter_t *it) {
Position *p = ecs_field(it, Position, 1);
Velocity *v = NULL;
if (it->field_count >= 2) {
v = ecs_field(it, Velocity, 2);
}
probe_iter(it);
int i;
for (i = 0; i < it->count; i ++) {
p[i].x ++;
if (v) {
v[i].x = p[i].x;
v[i].y = p[i].y;
}
}
}
static bool dummy_called = false;
static
void Dummy(ecs_iter_t *it) {
dummy_called = true;
}
void TriggerOnSet_set(void) {
ecs_world_t *world = ecs_mini();
ECS_COMPONENT(world, Position);
ECS_OBSERVER(world, OnSet, EcsOnSet, Position);
Probe ctx = {0};
ecs_set_ctx(world, &ctx, NULL);
ecs_entity_t e = ecs_new(world, Position);
test_int(ctx.count, 0);
ecs_set(world, e, Position, {10, 20});
test_int(ctx.count, 1);
test_int(ctx.invoked, 1);
test_int(ctx.system, OnSet);
test_int(ctx.term_count, 1);
test_null(ctx.param);
test_int(ctx.e[0], e);
test_int(ctx.c[0][0], ecs_id(Position));
test_int(ctx.s[0][0], 0);
const Position *p = ecs_get(world, e, Position);
test_assert(p != NULL);
test_int(p->x, 11);
test_int(p->y, 20);
ecs_fini(world);
}
void TriggerOnSet_set_new(void) {
ecs_world_t *world = ecs_mini();
ECS_COMPONENT(world, Position);
ECS_OBSERVER(world, OnSet, EcsOnSet, Position);
Probe ctx = {0};
ecs_set_ctx(world, &ctx, NULL);
ecs_entity_t e = ecs_set(world, 0, Position, {10, 20});
test_int(ctx.count, 1);
test_int(ctx.invoked, 1);
test_int(ctx.system, OnSet);
test_int(ctx.term_count, 1);
test_null(ctx.param);
test_int(ctx.e[0], e);
test_int(ctx.c[0][0], ecs_id(Position));
test_int(ctx.s[0][0], 0);
const Position *p = ecs_get(world, e, Position);
test_assert(p != NULL);
test_int(p->x, 11);
test_int(p->y, 20);
ecs_fini(world);
}
void TriggerOnSet_set_again(void) {
ecs_world_t *world = ecs_mini();
ECS_COMPONENT(world, Position);
ECS_OBSERVER(world, OnSet, EcsOnSet, Position);
Probe ctx = {0};
ecs_set_ctx(world, &ctx, NULL);
ecs_entity_t e = ecs_new(world, Position);
test_int(ctx.count, 0);
ecs_set(world, e, Position, {10, 20});
test_int(ctx.count, 1);
test_int(ctx.invoked, 1);
test_int(ctx.system, OnSet);
test_int(ctx.term_count, 1);
test_null(ctx.param);
test_int(ctx.e[0], e);
test_int(ctx.c[0][0], ecs_id(Position));
test_int(ctx.s[0][0], 0);
const Position *p = ecs_get(world, e, Position);
test_assert(p != NULL);
test_int(p->x, 11);
test_int(p->y, 20);
ecs_set_ptr(world, e, Position, p);
p = ecs_get(world, e, Position);
test_assert(p != NULL);
test_int(p->x, 12);
test_int(p->y, 20);
ecs_fini(world);
}
void TriggerOnSet_clone(void) {
ecs_world_t *world = ecs_mini();
ECS_COMPONENT(world, Position);
ECS_OBSERVER(world, OnSet, EcsOnSet, Position);
Probe ctx = {0};
ecs_set_ctx(world, &ctx, NULL);
ecs_entity_t e1 = ecs_set(world, 0, Position, {10, 20});
test_int(ctx.count, 1);
test_int(ctx.invoked, 1);
test_int(ctx.system, OnSet);
test_int(ctx.term_count, 1);
test_null(ctx.param);
test_int(ctx.e[0], e1);
test_int(ctx.c[0][0], ecs_id(Position));
test_int(ctx.s[0][0], 0);
const Position *p = ecs_get(world, e1, Position);
test_assert(p != NULL);
test_int(p->x, 11);
test_int(p->y, 20);
ecs_os_zeromem(&ctx);
ecs_clone(world, 0, e1, false);
/* OnSet function should not have been called, because value has not been
* copied */
test_int(ctx.count, 0);
ecs_fini(world);
}
void TriggerOnSet_clone_w_value(void) {
ecs_world_t *world = ecs_mini();
ECS_COMPONENT(world, Position);
ECS_OBSERVER(world, OnSet, EcsOnSet, Position);
Probe ctx = {0};
ecs_set_ctx(world, &ctx, NULL);
ecs_entity_t e1 = ecs_set(world, 0, Position, {10, 20});
test_int(ctx.count, 1);
test_int(ctx.invoked, 1);
test_int(ctx.system, OnSet);
test_int(ctx.term_count, 1);
test_null(ctx.param);
test_int(ctx.e[0], e1);
test_int(ctx.c[0][0], ecs_id(Position));
test_int(ctx.s[0][0], 0);
const Position *p = ecs_get(world, e1, Position);
test_assert(p != NULL);
test_int(p->x, 11);
test_int(p->y, 20);
ecs_os_zeromem(&ctx);
ecs_entity_t e2 = ecs_clone(world, 0, e1, true);
test_int(ctx.count, 1);
test_int(ctx.invoked, 1);
test_int(ctx.system, OnSet);
test_int(ctx.term_count, 1);
test_null(ctx.param);
test_int(ctx.e[0], e2);
test_int(ctx.c[0][0], ecs_id(Position));
test_int(ctx.s[0][0], 0);
p = ecs_get(world, e2, Position);
test_assert(p != NULL);
test_int(p->x, 12);
test_int(p->y, 20);
ecs_fini(world);
}
static bool add_called;
static bool set_called;
static
void OnAdd_check_order(ecs_iter_t *it) {
Position *p = ecs_field(it, Position, 1);
test_assert(!add_called);
test_assert(!set_called);
probe_iter(it);
int i;
for (i = 0; i < it->count; i ++) {
p[i].x = 1;
p[i].y = 2;
}
add_called = true;
}
static
void OnSet_check_order(ecs_iter_t *it) {
Position *p = ecs_field(it, Position, 1);
probe_iter(it);
test_assert(add_called);
test_assert(!set_called);
int i;
for (i = 0; i < it->count; i ++) {
p[i].x ++;
}
set_called = true;
}
void TriggerOnSet_set_and_add_system(void) {
ecs_world_t *world = ecs_mini();
ECS_COMPONENT(world, Position);
ECS_OBSERVER(world, OnSet_check_order, EcsOnSet, Position);
ECS_OBSERVER(world, OnAdd_check_order, EcsOnAdd, Position);
Probe ctx = {0};
ecs_set_ctx(world, &ctx, NULL);
ecs_entity_t e = ecs_new(world, 0);
test_int(ctx.count, 0);
ecs_set(world, e, Position, {10, 20});
test_int(ctx.count, 2);
test_int(ctx.invoked, 2);
test_int(ctx.system, OnSet_check_order);
test_int(ctx.term_count, 1);
test_null(ctx.param);
test_int(ctx.e[0], e);
test_int(ctx.e[1], e);
test_int(ctx.c[0][0], ecs_id(Position));
test_int(ctx.s[0][0], 0);
test_int(ctx.c[1][0], ecs_id(Position));
test_int(ctx.s[1][0], 0);
const Position *p = ecs_get(world, e, Position);
test_assert(p != NULL);
test_int(p->x, 11);
test_int(p->y, 20);
test_assert(set_called);
ecs_fini(world);
}
static
void OnSetShared(ecs_iter_t *it) {
Position *p = ecs_field(it, Position, 1);
Velocity *v = NULL;
if (it->field_count >= 2) {
v = ecs_field(it, Velocity, 2);
}
probe_iter(it);
int i;
for (i = 0; i < it->count; i ++) {
if (v) {
v[i].x = p->x;
v[i].y = p->y;
}
}
}
void TriggerOnSet_on_set_after_override(void) {
ecs_world_t *world = ecs_mini();
ECS_COMPONENT(world, Position);
ECS_PREFAB(world, Prefab, Position);
ecs_set(world, Prefab, Position, {1, 3});
ECS_OBSERVER(world, OnSetShared, EcsOnSet, Position);
Probe ctx = {0};
ecs_set_ctx(world, &ctx, NULL);
/* instantiate prefab */
ecs_entity_t e = ecs_new_w_pair(world, EcsIsA, Prefab);
test_int(ctx.count, 1);
test_int(ctx.invoked, 1);
test_int(ctx.system, OnSetShared);
test_int(ctx.term_count, 1);
test_null(ctx.param);
test_int(ctx.e[0], e);
test_int(ctx.c[0][0], ecs_id(Position));
test_int(ctx.s[0][0], Prefab);
const Position *p = ecs_get(world, e, Position);
test_assert(p != NULL);
test_assert(p == ecs_get(world, Prefab, Position));
test_int(p->x, 1);
test_int(p->y, 3);
/* Override component. Should not call OnSet system because the value of the
* component has not changed. */
ecs_os_zeromem(&ctx);
ecs_add(world, e, Position);
test_int(ctx.count, 0);
test_int(ctx.invoked, 0);
const Position *p_after = ecs_get(world, e, Position);
test_assert(p_after != NULL);
test_assert(p != p_after);
test_int(p_after->x, 1);
test_int(p_after->y, 3);
/* Set component */
ecs_set(world, e, Position, {2, 4});
test_int(ctx.count, 1);
test_int(ctx.invoked, 1);
test_int(ctx.system, OnSetShared);
test_int(ctx.term_count, 1);
test_null(ctx.param);
test_int(ctx.e[0], e);
test_int(ctx.c[0][0], ecs_id(Position));
test_int(ctx.s[0][0], 0);
p_after = ecs_get(world, e, Position);
test_assert(p_after != NULL);
test_assert(p != p_after);
test_int(p_after->x, 2);
test_int(p_after->y, 4);
ecs_fini(world);
}
void TriggerOnSet_on_set_after_override_w_new(void) {
ecs_world_t *world = ecs_mini();
ECS_COMPONENT(world, Position);
ECS_PREFAB(world, Prefab, Position, OVERRIDE | Position);
ecs_set(world, Prefab, Position, {1, 3});
Probe ctx = {0};
ecs_entity_t t1 = ecs_observer_init(world, &(ecs_observer_desc_t){
.filter.terms[0].id = ecs_id(Position),
.events = {EcsOnSet},
.callback = OnSet,
.ctx = &ctx
});
ecs_entity_t e = ecs_new_w_pair(world, EcsIsA, Prefab);
test_int(ctx.count, 1);
test_int(ctx.invoked, 1);
test_int(ctx.system, t1);
test_int(ctx.term_count, 1);
test_null(ctx.param);
test_int(ctx.e[0], e);
test_int(ctx.c[0][0], ecs_id(Position));
test_int(ctx.s[0][0], 0);
const Position *p = ecs_get(world, e, Position);
test_assert(p != NULL);
test_int(p->x, 2);
test_int(p->y, 3);
ecs_fini(world);
}
void TriggerOnSet_on_set_after_override_w_new_w_count(void) {
ecs_world_t *world = ecs_mini();
ECS_COMPONENT(world, Position);
ECS_PREFAB(world, Prefab, Position, OVERRIDE | Position);
ecs_set(world, Prefab, Position, {1, 3});
ECS_OBSERVER(world, OnSet, EcsOnSet, Position);
Probe ctx = {0};
ecs_set_ctx(world, &ctx, NULL);
const ecs_entity_t *ids = ecs_bulk_new_w_id(world, ecs_pair(EcsIsA, Prefab), 3);
test_assert(ids != NULL);
test_int(ctx.count, 3);
test_int(ctx.invoked, 1);
test_int(ctx.system, OnSet);
test_int(ctx.term_count, 1);
test_null(ctx.param);
test_int(ctx.e[0], ids[0]);
test_int(ctx.c[0][0], ecs_id(Position));
test_int(ctx.s[0][0], 0);
int i;
for (i = 0; i < 3; i ++) {
const Position *p = ecs_get(world, ids[i], Position);
test_assert(p != NULL);
test_int(p->x, 2);
test_int(p->y, 3);
}
ecs_fini(world);
}
void TriggerOnSet_on_set_after_override_1_of_2_overridden(void) {
ecs_world_t *world = ecs_mini();
ECS_COMPONENT(world, Position);
ECS_PREFAB(world, Prefab, Position, OVERRIDE | Position);
ecs_set(world, Prefab, Position, {1, 3});
ECS_OBSERVER(world, OnSet, EcsOnSet, Position);
Probe ctx = {0};
ecs_set_ctx(world, &ctx, NULL);
ecs_entity_t e = ecs_new_w_pair(world, EcsIsA, Prefab);
test_int(ctx.count, 1);
test_int(ctx.invoked, 1);
test_int(ctx.system, OnSet);
test_int(ctx.term_count, 1);
test_null(ctx.param);
test_int(ctx.e[0], e);
test_int(ctx.c[0][0], ecs_id(Position));
test_int(ctx.s[0][0], 0);
const Position *p = ecs_get(world, e, Position);
test_assert(p != NULL);
test_int(p->x, 2);
test_int(p->y, 3);
ecs_fini(world);
}
static
void SetPosition(ecs_iter_t *it) {
probe_iter(it);
}
void TriggerOnSet_on_set_after_snapshot_restore(void) {
ecs_world_t *world = ecs_mini();
ECS_COMPONENT(world, Position);
ECS_OBSERVER(world, SetPosition, EcsOnSet, Position);
const ecs_entity_t *ids = ecs_bulk_new(world, Position, 10);
test_assert(ids != NULL);
ecs_entity_t id_arr[10];
memcpy(id_arr, ids, sizeof(ecs_entity_t) * 10);
int32_t i;
for (i = 0; i < 10; i ++) {
test_assert(ecs_has(world, ids[i], Position));
ecs_set(world, ids[i], Position, {i, i * 2});
}
Probe ctx = { 0 };
ecs_set_ctx(world, &ctx, NULL);
ecs_snapshot_t *s = ecs_snapshot_take(world);
test_int(ctx.invoked, 0);
/* Delete one entity, so we have more confidence we're triggering on the
* right entities */
ecs_delete(world, id_arr[0]);
test_int(ctx.invoked, 0);
ecs_snapshot_restore(world, s);
test_int(ctx.count, 10);
test_int(ctx.invoked, 1);
test_int(ctx.system, SetPosition);
test_int(ctx.term_count, 1);
test_int(ctx.c[0][0], ecs_id(Position));
test_null(ctx.param);
for (i = 0; i < 10; i ++) {
test_int(ctx.e[i], id_arr[i]);
}
ecs_fini(world);
}
void TriggerOnSet_emplace(void) {
ecs_world_t *world = ecs_mini();
ECS_COMPONENT(world, Position);
ecs_observer_init(world, &(ecs_observer_desc_t){
.filter.terms[0].id = ecs_id(Position),
.events = {EcsOnSet},
.callback = Dummy
});
ecs_entity_t e = ecs_new_id(world);
test_assert(e != 0);
test_int(dummy_called, 0);
Position *p = ecs_emplace(world, e, Position);
test_assert(p != NULL);
test_int(dummy_called, 0);
ecs_modified(world, e, Position);
test_bool(dummy_called, true);
ecs_fini(world);
}
void TriggerOnSet_un_set_tag_w_remove(void) {
ecs_world_t *world = ecs_mini();
ECS_TAG(world, Tag);
ecs_observer_init(world, &(ecs_observer_desc_t){
.filter.terms[0].id = Tag,
.events = {EcsUnSet},
.callback = Dummy
});
ecs_entity_t e = ecs_new_id(world);
test_assert(e != 0);
test_int(dummy_called, 0);
ecs_add(world, e, Tag);
test_int(dummy_called, 0);
ecs_remove(world, e, Tag);
test_int(dummy_called, 1);
ecs_fini(world);
}
void TriggerOnSet_un_set_tag_w_clear(void) {
ecs_world_t *world = ecs_mini();
ECS_TAG(world, Tag);
ecs_observer_init(world, &(ecs_observer_desc_t){
.filter.terms[0].id = Tag,
.events = {EcsUnSet},
.callback = Dummy
});
ecs_entity_t e = ecs_new_id(world);
test_assert(e != 0);
test_int(dummy_called, 0);
ecs_add(world, e, Tag);
test_int(dummy_called, 0);
ecs_clear(world, e);
test_int(dummy_called, 1);
ecs_fini(world);
}
void TriggerOnSet_un_set_tag_w_delete(void) {
ecs_world_t *world = ecs_mini();
ECS_TAG(world, Tag);
ecs_observer_init(world, &(ecs_observer_desc_t){
.filter.terms[0].id = Tag,
.events = {EcsUnSet},
.callback = Dummy
});
ecs_entity_t e = ecs_new_id(world);
test_assert(e != 0);
test_int(dummy_called, 0);
ecs_add(world, e, Tag);
test_int(dummy_called, 0);
ecs_delete(world, e);
test_int(dummy_called, 1);
ecs_fini(world);
}
void TriggerOnSet_on_set_after_remove_override(void) {
ecs_world_t *world = ecs_mini();
ECS_COMPONENT(world, Position);
ECS_COMPONENT(world, Velocity);
ECS_ENTITY(world, Base, Position);
ECS_OBSERVER(world, Trigger, EcsOnSet, Position);
Probe ctx = { 0 };
ecs_set_ctx(world, &ctx, NULL);
ecs_entity_t e = ecs_new(world, Position);
test_int(ctx.invoked, 0);
ecs_add_pair(world, e, EcsIsA, Base);
test_int(ctx.invoked, 0);
ecs_remove(world, e, Position);
test_int(ctx.invoked, 1);
test_int(ctx.count, 1);
test_int(ctx.system, Trigger);
test_int(ctx.term_count, 1);
test_null(ctx.param);
test_int(ctx.e[0], e);
test_int(ctx.c[0][0], ecs_id(Position));
test_int(ctx.s[0][0], Base);
ecs_fini(world);
}

View File

@@ -0,0 +1,409 @@
#include <api.h>
#include <stdio.h>
static
char* type_str(ecs_world_t *world, ecs_entity_t type_ent) {
const ecs_type_t *t = ecs_get_type(world, type_ent);
test_assert(t != NULL);
return ecs_type_str(world, t);
}
void Type_setup(void) {
ecs_log_set_level(-2);
}
void Type_type_of_1_tostr(void) {
ecs_world_t *world = ecs_mini();
ECS_COMPONENT(world, Position);
ecs_type_t t = { .array = (ecs_id_t[]){ ecs_id(Position) }, .count = 1 };
char *str = ecs_type_str(world, &t);
test_str(str, "Position");
ecs_os_free(str);
ecs_fini(world);
}
void Type_type_of_2_tostr(void) {
ecs_world_t *world = ecs_mini();
ECS_COMPONENT(world, Position);
ECS_COMPONENT(world, Velocity);
ecs_type_t t = { .array = (ecs_id_t[]){
ecs_id(Position), ecs_id(Velocity)
}, .count = 2 };
char *str = ecs_type_str(world, &t);
test_str(str, "Position, Velocity");
ecs_os_free(str);
ecs_fini(world);
}
void Type_type_of_2_tostr_no_id(void) {
ecs_world_t *world = ecs_mini();
ecs_ensure(world, 100);
ecs_ensure(world, 200);
ecs_type_t t = { .array = (ecs_id_t[]){ 100, 200 }, .count = 2 };
char *str = ecs_type_str(world, &t);
test_str(str, "100, 200");
ecs_os_free(str);
ecs_fini(world);
}
void Type_invalid_entity_type_expression(void) {
install_test_abort();
ecs_world_t *world = ecs_mini();
ECS_COMPONENT(world, Velocity);
ECS_COMPONENT(world, Position);
ECS_ENTITY(world, Entity, Position);
test_expect_abort();
ECS_PREFAB(world, Type, Entity:Position, Velocity);
ecs_fini(world);
}
void Type_invalid_system_type_expression(void) {
install_test_abort();
ecs_world_t *world = ecs_mini();
ECS_COMPONENT(world, Velocity);
ECS_COMPONENT(world, Position);
test_expect_abort();
ECS_PREFAB(world, Type, Position(Type), Velocity);
ecs_fini(world);
}
void Type_get_type(void) {
ecs_world_t *world = ecs_mini();
ECS_COMPONENT(world, Position);
ecs_entity_t e = ecs_new(world, Position);
const ecs_type_t *t = ecs_get_type(world, e);
test_assert(t != NULL);
test_int(t->count, 1);
ecs_entity_t *type_array = t->array;
test_assert(type_array != NULL);
test_int(type_array[0], ecs_id(Position));
ecs_fini(world);
}
void Type_get_type_from_empty(void) {
ecs_world_t *world = ecs_mini();
ecs_entity_t e = ecs_new(world, 0);
const ecs_type_t *t = ecs_get_type(world, e);
test_assert(t == NULL);
ecs_fini(world);
}
void Type_get_type_from_0(void) {
install_test_abort();
ecs_world_t *world = ecs_mini();
test_expect_abort();
ecs_get_type(world, 0);
}
void Type_type_to_expr_pair(void) {
ecs_world_t *world = ecs_mini();
ecs_ensure(world, 100);
ecs_ensure(world, 200);
ecs_type_t t = { .array = (ecs_id_t[]){ ecs_pair(100, 200) }, .count = 1 };
char *str = ecs_type_str(world, &t);
test_str(str, "(100,200)");
ecs_os_free(str);
ecs_fini(world);
}
void Type_type_to_expr_pair_w_comp(void) {
ecs_world_t *world = ecs_mini();
ECS_COMPONENT(world, Position);
ECS_COMPONENT(world, Velocity);
ecs_type_t t = { .array = (ecs_id_t[]){
ecs_pair(ecs_id(Position), ecs_id(Velocity))
}, .count = 1 };
char *str = ecs_type_str(world, &t);
test_str(str, "(Position,Velocity)");
ecs_os_free(str);
ecs_fini(world);
}
void Type_type_to_expr_scope(void) {
ecs_world_t *world = ecs_mini();
ECS_COMPONENT(world, Position);
ECS_ENTITY(world, scope, 0);
ecs_set_scope(world, scope);
ECS_COMPONENT(world, Velocity);
ecs_set_scope(world, 0);
ecs_type_t t = { .array = (ecs_id_t[]){
ecs_pair(ecs_id(Position), ecs_id(Velocity))
}, .count = 1 };
char *str = ecs_type_str(world, &t);
test_str(str, "(Position,scope.Velocity)");
ecs_os_free(str);
ecs_fini(world);
}
void Type_type_to_expr_pair_w_override(void) {
ecs_world_t *world = ecs_mini();
ECS_COMPONENT(world, Position);
ECS_COMPONENT(world, Velocity);
ecs_type_t t = { .array = (ecs_id_t[]){
ECS_OVERRIDE | ecs_pair(ecs_id(Position), ecs_id(Velocity))
}, .count = 1 };
char *str = ecs_type_str(world, &t);
test_str(str, "OVERRIDE|(Position,Velocity)");
ecs_os_free(str);
ecs_fini(world);
}
void Type_entity_str(void) {
ecs_world_t *world = ecs_mini();
ECS_ENTITY(world, e, 0);
char *str = ecs_id_str(world, e);
test_str(str, "e");
ecs_os_free(str);
ecs_fini(world);
}
void Type_entity_path_str(void) {
ecs_world_t *world = ecs_mini();
ECS_ENTITY(world, parent, 0);
ECS_ENTITY(world, e, (ChildOf, parent));
char *str = ecs_id_str(world, e);
test_str(str, "parent.e");
ecs_os_free(str);
ecs_fini(world);
}
void Type_entity_instanceof_str(void) {
ecs_world_t *world = ecs_mini();
ECS_ENTITY(world, Foo, 0);
ecs_entity_t e = ecs_pair(EcsIsA, Foo);
char *str = ecs_id_str(world, e);
test_str(str, "(IsA,Foo)");
ecs_os_free(str);
ecs_fini(world);
}
void Type_entity_childof_str(void) {
ecs_world_t *world = ecs_mini();
ECS_ENTITY(world, Foo, 0);
ecs_entity_t e = ecs_pair(EcsChildOf, Foo);
char *str = ecs_id_str(world, e);
test_str(str, "(ChildOf,Foo)");
ecs_os_free(str);
ecs_fini(world);
}
void Type_entity_pair_str(void) {
ecs_world_t *world = ecs_mini();
ECS_ENTITY(world, Foo, 0);
ECS_ENTITY(world, Bar, 0);
ecs_entity_t e = ecs_pair(Bar, Foo);
char *str = ecs_id_str(world, e);
test_str(str, "(Bar,Foo)");
ecs_os_free(str);
ecs_fini(world);
}
void Type_entity_and_str(void) {
ecs_world_t *world = ecs_mini();
ECS_ENTITY(world, Foo, 0);
ecs_entity_t e = ECS_AND | Foo;
char *str = ecs_id_str(world, e);
test_str(str, "AND|Foo");
ecs_os_free(str);
ecs_fini(world);
}
void Type_entity_str_small_buffer(void) {
ecs_world_t *world = ecs_mini();
ECS_ENTITY(world, Foo, 0);
ecs_entity_t e = ecs_pair(EcsChildOf, Foo);
char *str = ecs_id_str(world, e);
test_str(str, "(ChildOf,Foo)");
ecs_os_free(str);
ecs_fini(world);
}
void Type_role_pair_str(void) {
ecs_entity_t e = ECS_PAIR;
test_str(ecs_id_flag_str(e), "PAIR");
}
void Type_role_and_str(void) {
ecs_entity_t e = ECS_AND;
test_str(ecs_id_flag_str(e), "AND");
}
void Type_role_owned_str(void) {
ecs_entity_t e = ECS_OVERRIDE;
test_str(ecs_id_flag_str(e), "OVERRIDE");
}
void Type_role_disabled_str(void) {
ecs_entity_t e = ECS_TOGGLE;
test_str(ecs_id_flag_str(e), "TOGGLE");
}
void Type_large_type_expr(void) {
ecs_world_t *world = ecs_mini();
int i;
for (i = 0; i < 64; i ++) {
char buff[4] = { 'e' };
sprintf(&buff[1], "%d", i + 1);
ecs_entity_init(world, &(ecs_entity_desc_t){
.name = buff
});
}
ecs_entity_t type_ent = ecs_entity_init(world, &(ecs_entity_desc_t){
.add_expr = "e1, e2, e3, e4, e5, e6, e7, e8, e9, e10,"
"e11, e12, e13, e14, e15, e16, e17, e18, e19, e20,"
"e21, e22, e23, e24, e25, e26, e27, e28, e29, e30,"
"e31, e32, e33, e34, e35, e36, e37, e38, e39, e40,"
"e41, e42, e43, e44, e45, e46, e47, e48, e49, e50,"
"e51, e52, e53, e54, e55, e56, e57, e58, e59, e60,"
"e61, e62, e63, e64"
});
test_assert(type_ent != 0);
const ecs_type_t *type = ecs_get_type(world, type_ent);
const ecs_table_t *table = ecs_get_table(world, type_ent);
test_assert(type != NULL);
test_assert(type->count == 64);
for (i = 0; i < 64; i ++) {
char buff[4] = { 'e' };
sprintf(&buff[1], "%d", i + 1);
ecs_entity_t e = ecs_lookup(world, buff);
test_assert(e != 0);
test_str(ecs_get_name(world, e), buff);
test_assert(ecs_search(world, table, e, 0) != -1);
}
ecs_fini(world);
}
void Type_large_type_expr_limit(void) {
ecs_world_t *world = ecs_mini();
test_assert(FLECS_ID_DESC_MAX == 32);
int i;
for (i = 0; i < 32; i ++) {
char buff[4] = { 'e' };
sprintf(&buff[1], "%d", i + 1);
ecs_entity_init(world, &(ecs_entity_desc_t){
.name = buff
});
}
ecs_entity_t type_ent = ecs_entity_init(world, &(ecs_entity_desc_t){
.add_expr = "e1, e2, e3, e4, e5, e6, e7, e8, e9, e10,"
"e11, e12, e13, e14, e15, e16, e17, e18, e19, e20,"
"e21, e22, e23, e24, e25, e26, e27, e28, e29, e30,"
"e31, e32"
});
test_assert(type_ent != 0);
const ecs_type_t *type = ecs_get_type(world, type_ent);
const ecs_table_t *table = ecs_get_table(world, type_ent);
test_assert(type != NULL);
test_assert(type->count == 32);
for (i = 0; i < 32; i ++) {
char buff[4] = { 'e' };
sprintf(&buff[1], "%d", i + 1);
ecs_entity_t e = ecs_lookup(world, buff);
test_assert(e != 0);
test_str(ecs_get_name(world, e), buff);
test_assert(ecs_search(world, table, e, 0) != -1);
}
ecs_fini(world);
}

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,382 @@
#include <api.h>
#define test_delta(prev, cur, field, value)\
test_int(value, (cur)->field - (prev)->field);\
(prev)->field = (cur)->field
void WorldInfo_get_tick(void) {
ecs_world_t *world = ecs_init();
const ecs_world_info_t *info = ecs_get_world_info(world);
test_assert(info != NULL);
test_int(info->frame_count_total, 0);
ecs_progress(world, 1);
test_int(info->frame_count_total, 1);
ecs_progress(world, 1);
test_int(info->frame_count_total, 2);
ecs_fini(world);
}
void WorldInfo_table_count(void) {
ecs_world_t *world = ecs_mini();
const ecs_world_info_t *cur = ecs_get_world_info(world);
test_assert(cur != NULL);
ecs_world_info_t prev = *cur;
ecs_entity_t c = ecs_new_id(world);
ecs_entity_t e = ecs_new_id(world);
test_delta(&prev, cur, table_count, 0);
ecs_add_id(world, e, c);
test_delta(&prev, cur, table_count, 1);
ecs_delete(world, c);
test_delta(&prev, cur, table_count, -1);
ecs_fini(world);
}
void WorldInfo_empty_table_count(void) {
ecs_world_t *world = ecs_mini();
const ecs_world_info_t *cur = ecs_get_world_info(world);
test_assert(cur != NULL);
ecs_world_info_t prev = *cur;
ecs_entity_t c = ecs_new_id(world);
ecs_entity_t e = ecs_new_id(world);
ecs_add_id(world, e, c);
ecs_run_aperiodic(world, 0);
test_delta(&prev, cur, empty_table_count, 0);
ecs_delete(world, e);
ecs_run_aperiodic(world, 0);
test_delta(&prev, cur, empty_table_count, 1);
ecs_delete(world, c);
ecs_run_aperiodic(world, 0);
test_delta(&prev, cur, empty_table_count, -1);
ecs_fini(world);
}
void WorldInfo_tag_table_count(void) {
ecs_world_t *world = ecs_mini();
const ecs_world_info_t *cur = ecs_get_world_info(world);
test_assert(cur != NULL);
ecs_world_info_t prev = *cur;
ecs_entity_t c = ecs_new_id(world);
ecs_entity_t e = ecs_new_id(world);
test_delta(&prev, cur, tag_table_count, 0);
ecs_add_id(world, e, c);
test_delta(&prev, cur, tag_table_count, 1);
ecs_fini(world);
}
void WorldInfo_trivial_table_count(void) {
ecs_world_t *world = ecs_mini();
ECS_COMPONENT(world, Position);
ECS_COMPONENT(world, Velocity);
/* Make it possible to delete components */
ecs_remove_pair(world, ecs_id(Position), EcsOnDelete, EcsWildcard);
ecs_remove_pair(world, ecs_id(Velocity), EcsOnDelete, EcsWildcard);
ecs_set_hooks(world, Velocity, {
.ctor = ecs_default_ctor
});
const ecs_world_info_t *cur = ecs_get_world_info(world);
test_assert(cur != NULL);
ecs_world_info_t prev = *cur;
ecs_entity_t e1 = ecs_new_id(world);
test_delta(&prev, cur, trivial_table_count, 0);
ecs_add(world, e1, Position);
test_delta(&prev, cur, trivial_table_count, 1);
ecs_entity_t e2 = ecs_new_id(world);
test_delta(&prev, cur, trivial_table_count, 0);
ecs_add(world, e2, Velocity);
test_delta(&prev, cur, trivial_table_count, 0);
ecs_delete(world, ecs_id(Position));
test_delta(&prev, cur, trivial_table_count, -1);
ecs_delete(world, ecs_id(Velocity));
test_delta(&prev, cur, trivial_table_count, 0);
ecs_fini(world);
}
void WorldInfo_table_record_count(void) {
ecs_world_t *world = ecs_mini();
const ecs_world_info_t *cur = ecs_get_world_info(world);
test_assert(cur != NULL);
ecs_world_info_t prev = *cur;
ecs_entity_t c_1 = ecs_new_id(world);
ecs_entity_t c_2 = ecs_new_id(world);
ecs_entity_t e = ecs_new_id(world);
test_delta(&prev, cur, table_record_count, 0);
ecs_add_id(world, e, c_1);
test_delta(&prev, cur, table_record_count, 4);
ecs_add_id(world, e, c_2);
test_delta(&prev, cur, table_record_count, 5);
ecs_delete(world, c_1);
test_delta(&prev, cur, table_record_count, -5);
ecs_delete(world, c_2);
test_delta(&prev, cur, table_record_count, -4);
ecs_fini(world);
}
void WorldInfo_table_storage_count(void) {
ecs_world_t *world = ecs_mini();
ECS_COMPONENT(world, Position);
/* Make it possible to delete components */
ecs_remove_pair(world, ecs_id(Position), EcsOnDelete, EcsWildcard);
const ecs_world_info_t *cur = ecs_get_world_info(world);
test_assert(cur != NULL);
ecs_world_info_t prev = *cur;
ecs_entity_t c_1 = ecs_new_id(world);
ecs_entity_t e = ecs_new_id(world);
ecs_add_id(world, e, c_1);
test_delta(&prev, cur, table_storage_count, 0);
ecs_add(world, e, Position);
test_delta(&prev, cur, table_storage_count, 1);
ecs_delete(world, c_1);
test_delta(&prev, cur, table_storage_count, 0);
ecs_delete(world, ecs_id(Position));
test_delta(&prev, cur, table_storage_count, -1);
ecs_fini(world);
}
void WorldInfo_table_create_count(void) {
ecs_world_t *world = ecs_mini();
const ecs_world_info_t *cur = ecs_get_world_info(world);
test_assert(cur != NULL);
ecs_world_info_t prev = *cur;
ecs_entity_t c_1 = ecs_new_id(world);
ecs_entity_t c_2 = ecs_new_id(world);
ecs_entity_t e = ecs_new_id(world);
test_delta(&prev, cur, table_create_total, 0);
ecs_add_id(world, e, c_1);
test_delta(&prev, cur, table_create_total, 1);
ecs_add_id(world, e, c_2);
test_delta(&prev, cur, table_create_total, 1);
ecs_delete(world, c_2);
ecs_delete(world, c_1);
test_delta(&prev, cur, table_create_total, 0);
ecs_fini(world);
}
void WorldInfo_table_delete_count(void) {
ecs_world_t *world = ecs_mini();
const ecs_world_info_t *cur = ecs_get_world_info(world);
test_assert(cur != NULL);
ecs_world_info_t prev = *cur;
ecs_entity_t c_1 = ecs_new_id(world);
ecs_entity_t c_2 = ecs_new_id(world);
ecs_entity_t e = ecs_new_id(world);
ecs_add_id(world, e, c_1);
test_delta(&prev, cur, table_delete_total, 0);
ecs_add_id(world, e, c_2);
test_delta(&prev, cur, table_delete_total, 0);
ecs_entity_t e2 = ecs_new_id(world);
ecs_add_id(world, e2, c_2);
test_delta(&prev, cur, table_delete_total, 0);
ecs_delete(world, c_1);
test_delta(&prev, cur, table_delete_total, 2);
ecs_delete(world, c_2);
test_delta(&prev, cur, table_delete_total, 1);
ecs_fini(world);
}
void WorldInfo_id_count(void) {
ecs_world_t *world = ecs_mini();
const ecs_world_info_t *cur = ecs_get_world_info(world);
test_assert(cur != NULL);
ecs_world_info_t prev = *cur;
ecs_entity_t c_1 = ecs_new_id(world);
ecs_entity_t c_2 = ecs_new_id(world);
ecs_entity_t e = ecs_new_id(world);
test_delta(&prev, cur, id_count, 0);
ecs_add_id(world, e, c_1);
test_delta(&prev, cur, id_count, 1);
ecs_add_id(world, e, c_2);
test_delta(&prev, cur, id_count, 1);
ecs_delete(world, c_1);
test_delta(&prev, cur, id_count, -1);
ecs_delete(world, c_2);
test_delta(&prev, cur, id_count, -1);
ecs_fini(world);
}
void WorldInfo_id_tag_component_count(void) {
ecs_world_t *world = ecs_mini();
const ecs_world_info_t *cur = ecs_get_world_info(world);
test_assert(cur != NULL);
ECS_COMPONENT(world, Position);
/* Make it possible to delete components */
ecs_remove_pair(world, ecs_id(Position), EcsOnDelete, EcsWildcard);
ecs_world_info_t prev_1 = *cur;
ecs_world_info_t prev_2 = *cur;
ecs_entity_t c_1 = ecs_new_id(world);
ecs_entity_t c_2 = ecs_new_id(world);
ecs_entity_t e = ecs_new_id(world);
test_delta(&prev_1, cur, tag_id_count, 0);
test_delta(&prev_2, cur, component_id_count, 0);
ecs_add_id(world, e, c_1);
test_delta(&prev_1, cur, tag_id_count, 1);
test_delta(&prev_2, cur, component_id_count, 0);
ecs_add_id(world, e, c_2);
test_delta(&prev_1, cur, tag_id_count, 1);
test_delta(&prev_2, cur, component_id_count, 0);
ecs_add(world, e, Position);
test_delta(&prev_1, cur, tag_id_count, 0);
test_delta(&prev_2, cur, component_id_count, 0);
ecs_delete(world, c_1);
test_delta(&prev_1, cur, tag_id_count, -1);
test_delta(&prev_2, cur, component_id_count, 0);
ecs_delete(world, c_2);
test_delta(&prev_1, cur, tag_id_count, -1);
test_delta(&prev_2, cur, component_id_count, 0);
ecs_delete(world, ecs_id(Position));
test_delta(&prev_1, cur, tag_id_count, 0);
test_delta(&prev_2, cur, component_id_count, -1);
ecs_fini(world);
}
void WorldInfo_id_pair_count(void) {
ecs_world_t *world = ecs_mini();
const ecs_world_info_t *cur = ecs_get_world_info(world);
test_assert(cur != NULL);
ecs_world_info_t prev = *cur;
ecs_entity_t c_1 = ecs_new_id(world);
ecs_entity_t c_2 = ecs_new_id(world);
ecs_entity_t e = ecs_new_id(world);
test_delta(&prev, cur, pair_id_count, 0);
ecs_add_id(world, e, c_1);
test_delta(&prev, cur, pair_id_count, 0);
ecs_add_id(world, e, c_2);
test_delta(&prev, cur, pair_id_count, 0);
ecs_add_pair(world, e, c_1, c_2);
test_delta(&prev, cur, pair_id_count, 1);
ecs_delete(world, c_1);
test_delta(&prev, cur, pair_id_count, -1);
ecs_delete(world, c_2);
test_delta(&prev, cur, pair_id_count, 0);
ecs_fini(world);
}
void WorldInfo_id_wildcard_count(void) {
ecs_world_t *world = ecs_mini();
const ecs_world_info_t *cur = ecs_get_world_info(world);
test_assert(cur != NULL);
ecs_world_info_t prev = *cur;
ecs_entity_t c_1 = ecs_new_id(world);
ecs_entity_t c_2 = ecs_new_id(world);
ecs_entity_t c_3 = ecs_new_id(world);
ecs_entity_t e = ecs_new_id(world);
test_delta(&prev, cur, wildcard_id_count, 0);
ecs_add_id(world, e, c_1);
test_delta(&prev, cur, wildcard_id_count, 0);
ecs_add_id(world, e, c_2);
test_delta(&prev, cur, wildcard_id_count, 0);
ecs_add_pair(world, e, c_1, c_2);
test_delta(&prev, cur, wildcard_id_count, 2);
ecs_add_pair(world, e, c_3, c_2);
test_delta(&prev, cur, wildcard_id_count, 1);
ecs_delete(world, c_1);
test_delta(&prev, cur, wildcard_id_count, -1);
ecs_delete(world, c_3);
test_delta(&prev, cur, wildcard_id_count, -1);
ecs_delete(world, c_2);
test_delta(&prev, cur, wildcard_id_count, -1);
ecs_fini(world);
}

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,319 @@
#include <api.h>
#include <stdio.h>
void probe_system_w_ctx(
ecs_iter_t *it,
Probe *ctx)
{
if (!ctx) {
return;
}
ctx->param = it->param;
ctx->system = it->system;
ctx->event = it->event;
ctx->event_id = it->event_id;
ctx->offset = 0;
ctx->term_count = it->field_count;
ctx->term_index = it->term_index;
int i;
for (i = 0; i < ctx->term_count; i ++) {
ctx->c[ctx->invoked][i] = it->ids[i];
ctx->s[ctx->invoked][i] = ecs_field_src(it, i + 1);
ecs_id_t e = ecs_field_id(it, i + 1);
test_assert(e != 0);
}
for (i = 0; i < it->count; i ++) {
if (i + ctx->count < 256) {
ctx->e[i + ctx->count] = it->entities[i];
} else {
/* can't store more than that, tests shouldn't rely on
* getting back more than 256 results */
}
}
ctx->count += it->count;
ctx->invoked ++;
}
void probe_iter(
ecs_iter_t *it)
{
Probe *ctx = ecs_get_ctx(it->world);
if (!ctx) {
ctx = it->ctx;
}
probe_system_w_ctx(it, ctx);
}
void probe_has_entity(Probe *probe, ecs_entity_t e) {
int i;
for (i = 0; i < probe->count; i ++) {
if (probe->e[i] == e) {
break;
}
}
test_assert(i != probe->count);
}
void install_test_abort(void) {
ecs_os_set_api_defaults();
ecs_os_api_t os_api = ecs_os_get_api();
os_api.abort_ = test_abort;
ecs_os_set_api(&os_api);
ecs_log_set_level(-5);
}
const ecs_entity_t* bulk_new_w_type(
ecs_world_t *world, ecs_entity_t type_ent, int32_t count)
{
const ecs_type_t *type = ecs_get_type(world, type_ent);
test_assert(type != NULL);
ecs_id_t *ids = type->array;
int i = 0;
while ((ecs_id_get_flags(world, ids[i]) & EcsIdDontInherit)) {
i ++;
}
const ecs_entity_t *result = ecs_bulk_new_w_id(world, ids[i], count);
for (; i < type->count; i ++) {
for (int e = 0; e < count; e ++) {
if (ecs_id_get_flags(world, ids[i]) & EcsIdDontInherit) {
continue;
}
ecs_add_id(world, result[e], ids[i]);
}
}
return result;
}
int32_t find_entity(
ecs_world_t *world,
test_iter_result_t *expect,
ecs_entity_t e)
{
int i;
for (i = 0; i < ITER_MAX_ENTITIES; i ++) {
if (expect->entities[i] == e) {
while (expect->matched[i]) {
i ++;
if (!if_test_assert(e == expect->entities[i])) {
return -1;
}
}
if (expect->entity_names[i]) {
if (!if_test_str(ecs_get_name(world, e), expect->entity_names[i])) {
return -1;
}
}
return i;
}
}
for (i = 0; i < ITER_MAX_ENTITIES; i ++) {
if (!expect->entity_names[i]) {
break;
}
if (!strcmp(ecs_get_name(world, e), expect->entity_names[i])) {
while (expect->matched[i]) {
i ++;
// If this fails, the entity is encountered more times than
// expected.
if (!if_test_str(ecs_get_name(world, e),
expect->entity_names[i]))
{
return -1;
}
}
return i;
}
}
return -1;
}
bool test_iter(
ecs_iter_t *it,
ecs_iter_next_action_t next,
test_iter_result_t *expect)
{
int32_t entity_index = -1;
while (next(it)) {
int i;
for (i = 0; (i < it->count) || (i < 1); i ++) {
ecs_entity_t e = 0;
int t;
if (it->count) {
e = it->entities[i];
entity_index = find_entity(it->world, expect, e);
// Matched unexpected entity
test_assert(entity_index != -1);
expect->matched[entity_index] = true;
// Test data
for (t = 0; t < it->field_count; t++) {
size_t size = ecs_field_size(it, t + 1);
if (!size) {
continue;
}
void *expect_ptr = expect->term_columns[t];
if (!expect_ptr) {
continue;
}
expect_ptr = ECS_OFFSET(expect_ptr, size * entity_index);
void *component_ptr = ecs_field_w_size(it, size, t + 1);
if (!if_test_assert(component_ptr != NULL)) {
return false;
}
component_ptr = ECS_OFFSET(component_ptr, size * i);
if (!if_test_assert(memcpy(component_ptr, expect_ptr, size))) {
return false;
}
}
} else {
entity_index ++;
}
// Test ids
ecs_id_t *ids = expect->term_ids[entity_index];
if (!ids[0]) {
ids = expect->term_ids[0];
}
for (t = 0; t < it->field_count; t++) {
if (!ids[t]) {
break;
}
if (!if_test_assert(ecs_field_id(it, t + 1) == ids[t])) {
return false;
}
}
if (!if_test_assert(ids[t] == 0)) {
return false;
}
// Test ids by expr
char **ids_expect = expect->term_ids_expr[entity_index];
if (!ids_expect) {
ids_expect = expect->term_ids_expr[0];
}
for (t = 0; t < it->field_count; t++) {
if (!ids_expect[t]) {
break;
}
char *id_found = ecs_id_str(it->world, ecs_field_id(it, t + 1));
if (!if_test_str(id_found, ids_expect[t])) {
printf(" - term %d\n", t);
if (e) {
printf(" - matched entity %u (%s, [%s])\n",
(uint32_t)e,
ecs_get_name(it->world, e),
ecs_type_str(it->world, ecs_get_type(it->world, e)));
if (expect->entities[i]) {
printf(" - expected entity %u (%s)\n",
(uint32_t)expect->entities[i],
ecs_get_name(it->world, expect->entities[i]));
} else if (expect->entity_names[i]) {
printf(" - expected entity %s\n",
expect->entity_names[i]);
}
}
printf(" - @ result index %d\n", entity_index);
return false;
}
ecs_os_free(id_found);
}
if (!if_test_assert(ids_expect[t] == NULL)) {
return false;
}
// Test variables
int v;
for (v = 0; v < ITER_MAX_VARIABLES; v++) {
int32_t id = expect->variables[v].id;
if (!id) {
break;
}
ecs_entity_t e = expect->variables[v].entities[entity_index];
if (!e) {
e = expect->variables[v].entities[0];
}
if (e) {
ecs_entity_t var = ecs_iter_get_var(it, id);
if (!if_test_assert(e == var)) {
return false;
}
}
const char *name = expect->variables[v].entity_names[entity_index];
if (!name) {
name = expect->variables[v].entity_names[0];
}
if (name) {
ecs_entity_t var = ecs_iter_get_var(it, id);
if (!if_test_str(name, ecs_get_name(it->world, var))) {
printf(" - variable id %d\n", id);
printf(" - index %d\n", entity_index);
return false;
}
}
/* If a variable id is set, either an entity or entity name must
* be set. */
if (!if_test_assert(e || name)) {
return false;
}
}
}
expect->table_count_actual ++;
}
for (int i = 0; i < ITER_MAX_ENTITIES; i ++) {
if (expect->entities[i] || expect->entity_names[i]) {
if (!if_test_assert(expect->matched[i])) {
printf(" - entity %u (%s) at index %d not matched\n",
(uint32_t)expect->entities[i], expect->entity_names[i], i);
return false;
}
}
}
if (expect->table_count_expect) {
if (!if_test_assert(expect->table_count_actual == expect->table_count_expect)) {
return false;
}
}
return true;
}