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

2988 lines
77 KiB
C

#include <api.h>
typedef struct Rel {
float value;
} Rel;
typedef struct RelA {
float value;
} RelA;
typedef struct RelB {
float value;
} RelB;
typedef struct Obj {
float value;
} Obj;
void ProcessPairs(ecs_iter_t *it) {
Rel *tr = ecs_field(it, Rel, 1);
probe_iter(it);
if (tr) {
int32_t i;
for (i = 0; i < it->count; i ++) {
tr[i].value ++;
}
}
}
void Pairs_type_w_one_pair(void) {
ecs_world_t *world = ecs_init();
ECS_COMPONENT(world, Position);
ECS_COMPONENT(world, Velocity);
ECS_COMPONENT(world, Rel);
ECS_SYSTEM(world, ProcessPairs, EcsOnUpdate, (Rel, *));
/* Ensure that pair is matched against different components */
ecs_entity_t e1 = ecs_set_pair(world, 0, Rel, ecs_id(Position), {
.value = 10
});
test_assert(e1 != 0);
test_assert( ecs_has_pair(world, e1, ecs_id(Rel), ecs_id(Position)));
ecs_entity_t e2 = ecs_set_pair(world, 0, Rel, ecs_id(Velocity), {
.value = 20
});
test_assert(e2 != 0);
test_assert( ecs_has_pair(world, e2, ecs_id(Rel), ecs_id(Velocity)));
Probe ctx = {0};
ecs_set_ctx(world, &ctx, NULL);
ecs_progress(world, 0);
const Rel* tr = ecs_get_pair(world, e1, Rel, ecs_id(Position));
test_assert(tr != NULL);
test_int(tr->value, 11);
tr = ecs_get_pair(world, e2, Rel, ecs_id(Velocity));
test_assert(tr != NULL);
test_int(tr->value, 21);
test_int(ctx.count, 2);
test_int(ctx.invoked, 2);
test_int(ctx.system, ProcessPairs);
test_int(ctx.term_count, 1);
test_null(ctx.param);
test_int(ctx.e[0], e1);
test_int(ctx.e[1], e2);
ecs_entity_t c = ctx.c[0][0];
ecs_entity_t hi = ECS_PAIR_FIRST(c);
ecs_entity_t lo = ECS_PAIR_SECOND(c);
test_int(hi, ecs_id(Rel));
test_int(lo, ecs_id(Position));
c = ctx.c[1][0];
hi = ECS_PAIR_FIRST(c);
lo = ECS_PAIR_SECOND(c);
test_int(hi, ecs_id(Rel));
test_int(lo, ecs_id(Velocity));
test_int(ctx.s[0][0], 0);
test_int(ctx.s[1][0], 0);
ecs_fini(world);
}
void Pairs_type_w_two_pairs(void) {
ecs_world_t *world = ecs_init();
ECS_COMPONENT(world, Position);
ECS_COMPONENT(world, Velocity);
ECS_COMPONENT(world, Rel);
ECS_SYSTEM(world, ProcessPairs, EcsOnUpdate, (Rel, *));
/* Ensure that pair is matched against different components on same entity */
ecs_entity_t e1 = ecs_new(world, 0);
ecs_set_pair(world, e1, Rel, ecs_id(Position), {
.value = 10
});
test_assert( ecs_has_pair(world, e1, ecs_id(Rel), ecs_id(Position)));
ecs_set_pair(world, e1, Rel, ecs_id(Velocity), {
.value = 20
});
test_assert( ecs_has_pair(world, e1, ecs_id(Rel), ecs_id(Velocity)));
ecs_entity_t e2 = ecs_new(world, 0);
ecs_set_pair(world, e2, Rel, ecs_id(Position), {
.value = 30
});
test_assert( ecs_has_pair(world, e2, ecs_id(Rel), ecs_id(Position)));
ecs_set_pair(world, e2, Rel, ecs_id(Velocity), {
.value = 40
});
test_assert( ecs_has_pair(world, e2, ecs_id(Rel), ecs_id(Position)));
Probe ctx = {0};
ecs_set_ctx(world, &ctx, NULL);
ecs_progress(world, 0);
const Rel* tr = ecs_get_pair(world, e1, Rel, ecs_id(Position));
test_assert(tr != NULL);
test_int(tr->value, 11);
tr = ecs_get_pair(world, e1, Rel, ecs_id(Velocity));
test_assert(tr != NULL);
test_int(tr->value, 21);
tr = ecs_get_pair(world, e2, Rel, ecs_id(Position));
test_assert(tr != NULL);
test_int(tr->value, 31);
tr = ecs_get_pair(world, e2, Rel, ecs_id(Velocity));
test_assert(tr != NULL);
test_int(tr->value, 41);
test_int(ctx.count, 4);
test_int(ctx.invoked, 2);
test_int(ctx.system, ProcessPairs);
test_int(ctx.term_count, 1);
test_null(ctx.param);
test_int(ctx.e[0], e1);
test_int(ctx.e[1], e2);
test_int(ctx.e[2], e1);
test_int(ctx.e[3], e2);
ecs_entity_t c = ctx.c[0][0];
ecs_entity_t hi = ECS_PAIR_FIRST(c);
ecs_entity_t lo = ECS_PAIR_SECOND(c);
test_int(hi, ecs_id(Rel));
test_int(lo, ecs_id(Position));
c = ctx.c[1][0];
hi = ECS_PAIR_FIRST(c);
lo = ECS_PAIR_SECOND(c);
test_int(hi, ecs_id(Rel));
test_int(lo, ecs_id(Velocity));
test_int(ctx.s[0][0], 0);
test_int(ctx.s[1][0], 0);
test_int(ctx.s[2][0], 0);
test_int(ctx.s[3][0], 0);
ecs_fini(world);
}
void Pairs_add_pair(void) {
ecs_world_t *world = ecs_mini();
ECS_COMPONENT(world, Position);
ECS_COMPONENT(world, Velocity);
ECS_COMPONENT(world, Rel);
ecs_entity_t e1 = ecs_new(world, 0);
test_assert(e1 != 0);
ecs_add_pair(world, e1, ecs_id(Rel), ecs_id(Position));
test_assert( ecs_has_pair(world, e1, ecs_id(Rel), ecs_id(Position)));
ecs_fini(world);
}
void Pairs_remove_pair(void) {
ecs_world_t *world = ecs_mini();
ECS_COMPONENT(world, Position);
ECS_COMPONENT(world, Velocity);
ECS_COMPONENT(world, Rel);
ecs_entity_t e1 = ecs_set_pair(world, 0, Rel, ecs_id(Position), {
.value = 10
});
test_assert(e1 != 0);
test_assert( ecs_has_pair(world, e1, ecs_id(Rel), ecs_id(Position)));
ecs_remove_pair(world, e1, ecs_id(Rel), ecs_id(Position));
test_assert( !ecs_has_pair(world, e1, ecs_id(Rel), ecs_id(Position)));
ecs_fini(world);
}
void ProcessPairTags(ecs_iter_t *it) {
probe_iter(it);
}
void Pairs_add_tag_pair_for_tag(void) {
ecs_world_t *world = ecs_init();
ECS_TAG(world, Tag1);
ECS_TAG(world, Tag2);
ECS_TAG(world, Rel);
ECS_SYSTEM(world, ProcessPairTags, EcsOnUpdate, (Rel, *));
/* Ensure that pair is matched against different components */
ecs_entity_t e1 = ecs_new(world, 0);
ecs_add_pair(world, e1, Rel, Tag1);
test_assert(e1 != 0);
test_assert( ecs_has_pair(world, e1, Rel, Tag1));
ecs_entity_t e2 = ecs_new(world, 0);
ecs_add_pair(world, e2, Rel, Tag2);
test_assert(e2 != 0);
test_assert( ecs_has_pair(world, e2, Rel, Tag2));
Probe ctx = {0};
ecs_set_ctx(world, &ctx, NULL);
ecs_progress(world, 0);
test_int(ctx.count, 2);
test_int(ctx.invoked, 2);
test_int(ctx.system, ProcessPairTags);
test_int(ctx.term_count, 1);
test_null(ctx.param);
test_int(ctx.e[0], e1);
test_int(ctx.e[1], e2);
ecs_entity_t c = ctx.c[0][0];
ecs_entity_t hi = ECS_PAIR_FIRST(c);
ecs_entity_t lo = ECS_PAIR_SECOND(c);
test_int(hi, Rel);
test_int(lo, Tag1);
c = ctx.c[1][0];
hi = ECS_PAIR_FIRST(c);
lo = ECS_PAIR_SECOND(c);
test_int(hi, Rel);
test_int(lo, Tag2);
test_int(ctx.s[0][0], 0);
test_int(ctx.s[1][0], 0);
ecs_fini(world);
}
void ProcessValuePairs(ecs_iter_t *it) {
/* Strictly speaking this can be either Position or Velocity, but they have
* the same layout. */
Position *p = ecs_field(it, Position, 1);
probe_iter(it);
if (p) {
int32_t i;
for (i = 0; i < it->count; i ++) {
p[i].x += 10;
p[i].y += 20;
}
}
}
void Pairs_add_tag_pair_for_component(void) {
ecs_world_t *world = ecs_init();
ECS_COMPONENT(world, Position);
ECS_COMPONENT(world, Velocity);
ECS_TAG(world, Rel);
ECS_SYSTEM(world, ProcessValuePairs, EcsOnUpdate, (Rel, *));
ecs_entity_t e1 = ecs_set_pair_object(world, 0, Rel, Position, {
.x = 1,
.y = 2
});
test_assert( ecs_has_pair(world, e1, Rel, ecs_id(Position)));
ecs_entity_t e2 = ecs_set_pair_object(world, 0, Rel, Velocity, {
.x = 3,
.y = 4
});
test_assert( ecs_has_pair(world, e2, Rel, ecs_id(Velocity)));
Probe ctx = {0};
ecs_set_ctx(world, &ctx, NULL);
ecs_progress(world, 0);
test_int(ctx.count, 2);
test_int(ctx.invoked, 2);
test_int(ctx.system, ProcessValuePairs);
test_int(ctx.term_count, 1);
test_null(ctx.param);
test_int(ctx.e[0], e1);
test_int(ctx.e[1], e2);
ecs_entity_t c = ctx.c[0][0];
ecs_entity_t hi = ECS_PAIR_FIRST(c);
ecs_entity_t lo = ECS_PAIR_SECOND(c);
test_int(hi, Rel);
test_int(lo, ecs_id(Position));
c = ctx.c[1][0];
hi = ECS_PAIR_FIRST(c);
lo = ECS_PAIR_SECOND(c);
test_int(hi, Rel);
test_int(lo, ecs_id(Velocity));
test_int(ctx.s[0][0], 0);
test_int(ctx.s[1][0], 0);
ecs_fini(world);
}
void ProcessTwoPairs(ecs_iter_t *it) {
RelA *tr_a = ecs_field(it, RelA, 1);
RelB *tr_b = ecs_field(it, RelB, 2);
probe_iter(it);
int32_t i;
for (i = 0; i < it->count; i ++) {
tr_a[i].value ++;
tr_b[i].value ++;
}
}
void Pairs_query_2_pairs(void) {
ecs_world_t *world = ecs_init();
ECS_COMPONENT(world, Position);
ECS_COMPONENT(world, RelA);
ECS_COMPONENT(world, RelB);
ECS_SYSTEM(world, ProcessTwoPairs, EcsOnUpdate, (RelA, *), (RelB, *));
/* Create entity with both RelA and RelB */
ecs_entity_t e1 = ecs_set_pair(world, 0, RelA, ecs_id(Position), {
.value = 1
});
ecs_set_pair(world, e1, RelB, ecs_id(Position), {
.value = 2
});
test_assert( ecs_has_pair(world, e1, ecs_id(RelA), ecs_id(Position)));
test_assert( ecs_has_pair(world, e1, ecs_id(RelB), ecs_id(Position)));
/* Create entity with only RelA. Should not be matched with system */
ecs_entity_t e2 = ecs_set_pair(world, 0, RelA, ecs_id(Position), {
.value = 3
});
test_assert( ecs_has_pair(world, e2, ecs_id(RelA), ecs_id(Position)));
/* Run system */
Probe ctx = {0};
ecs_set_ctx(world, &ctx, NULL);
ecs_progress(world, 0);
const RelA *tr_a = ecs_get_pair(world, e1, RelA, ecs_id(Position));
test_int(tr_a->value, 2);
const RelB *tr_b = ecs_get_pair(world, e1, RelB, ecs_id(Position));
test_int(tr_b->value, 3);
tr_a = ecs_get_pair(world, e2, RelA, ecs_id(Position));
test_int(tr_a->value, 3);
test_int(ctx.count, 1);
test_int(ctx.invoked, 1);
test_int(ctx.system, ProcessTwoPairs);
test_int(ctx.term_count, 2);
test_null(ctx.param);
test_int(ctx.e[0], e1);
ecs_entity_t c = ctx.c[0][0];
ecs_entity_t hi = ECS_PAIR_FIRST(c);
ecs_entity_t lo = ECS_PAIR_SECOND(c);
test_int(hi, ecs_id(RelA));
test_int(lo, ecs_id(Position));
c = ctx.c[0][1];
hi = ECS_PAIR_FIRST(c);
lo = ECS_PAIR_SECOND(c);
test_int(hi, ecs_id(RelB));
test_int(lo, ecs_id(Position));
ecs_fini(world);
}
void Pairs_query_2_pairs_2_instances_per_type(void) {
ecs_world_t *world = ecs_init();
ECS_COMPONENT(world, Position);
ECS_COMPONENT(world, Velocity);
ECS_COMPONENT(world, RelA);
ECS_COMPONENT(world, RelB);
ECS_SYSTEM(world, ProcessTwoPairs, EcsOnUpdate, (RelA, *), (RelB, *));
/* Create entity with both RelA and RelB, applied to two components*/
ecs_entity_t e1 = ecs_set_pair(world, 0, RelA, ecs_id(Position), {
.value = 1
});
ecs_set_pair(world, e1, RelB, ecs_id(Position), {
.value = 2
});
ecs_set_pair(world, e1, RelA, ecs_id(Velocity), {
.value = 3
});
ecs_set_pair(world, e1, RelB, ecs_id(Velocity), {
.value = 4
});
test_assert( ecs_has_pair(world, e1, ecs_id(RelA), ecs_id(Position)));
test_assert( ecs_has_pair(world, e1, ecs_id(RelB), ecs_id(Position)));
test_assert( ecs_has_pair(world, e1, ecs_id(RelA), ecs_id(Velocity)));
test_assert( ecs_has_pair(world, e1, ecs_id(RelB), ecs_id(Velocity)));
/* Run system */
Probe ctx = {0};
ecs_set_ctx(world, &ctx, NULL);
ecs_progress(world, 0);
const RelA *tr_a = ecs_get_pair(world, e1, RelA, ecs_id(Position));
test_int(tr_a->value, 3);
tr_a = ecs_get_pair(world, e1, RelA, ecs_id(Velocity));
test_int(tr_a->value, 5);
const RelB *tr_b = ecs_get_pair(world, e1, RelB, ecs_id(Position));
test_int(tr_b->value, 4);
tr_b = ecs_get_pair(world, e1, RelB, ecs_id(Velocity));
test_int(tr_b->value, 6);
test_int(ctx.count, 4);
test_int(ctx.invoked, 4);
test_int(ctx.system, ProcessTwoPairs);
test_int(ctx.term_count, 2);
test_null(ctx.param);
test_int(ctx.e[0], e1);
test_int(ctx.e[1], e1);
test_int(ctx.e[2], e1);
test_int(ctx.e[3], e1);
ecs_fini(world);
}
void Pairs_override_pair(void) {
ecs_world_t *world = ecs_mini();
ECS_COMPONENT(world, Position);
ECS_COMPONENT(world, Rel);
ecs_entity_t base = ecs_new(world, 0);
ecs_set_pair(world, base, Rel, ecs_id(Position), {.value = 10});
ecs_entity_t instance = ecs_new_w_pair(world, EcsIsA, base);
test_assert(ecs_has_pair(world, instance, ecs_id(Rel), ecs_id(Position)));
const Rel *t = ecs_get_pair(world, instance, Rel, ecs_id(Position));
test_assert(t != NULL);
test_int(t->value, 10);
const Rel *t_2 = ecs_get_pair(world, base, Rel, ecs_id(Position));
test_assert(t_2 != NULL);
test_assert(t == t_2);
ecs_add_pair(world, instance, ecs_id(Rel), ecs_id(Position));
t = ecs_get_pair(world, instance, Rel, ecs_id(Position));
test_assert(t != NULL);
test_int(t->value, 10);
test_assert(t != t_2);
ecs_fini(world);
}
void Pairs_override_tag_pair(void) {
ecs_world_t *world = ecs_mini();
ECS_COMPONENT(world, Position);
ECS_TAG(world, Rel);
ecs_entity_t base = ecs_new(world, 0);
ecs_set_pair_object(world, base, Rel, Position, {.x = 10, .y = 20});
ecs_entity_t instance = ecs_new_w_pair(world, EcsIsA, base);
test_assert(ecs_has_pair(world, instance, Rel, ecs_id(Position)));
const Position *t = ecs_get_pair_object(world, instance, Rel, Position);
test_assert(t != NULL);
test_int(t->x, 10);
test_int(t->y, 20);
const Position *t_2 = ecs_get_pair_object(world, base, Rel, Position);
test_assert(t_2 != NULL);
test_assert(t == t_2);
ecs_add_pair(world, instance, Rel, ecs_id(Position));
t = ecs_get_pair_object(world, instance, Rel, Position);
test_assert(t != NULL);
test_int(t->x, 10);
test_int(t->y, 20);
test_assert(t != t_2);
ecs_fini(world);
}
static
void PairTrigger(ecs_iter_t *it) {
probe_iter(it);
}
void Pairs_on_add_pair(void) {
ecs_world_t *world = ecs_mini();
ECS_COMPONENT(world, Position);
ECS_COMPONENT(world, Velocity);
ECS_COMPONENT(world, Rel);
ECS_OBSERVER(world, PairTrigger, EcsOnAdd, (Rel, *));
Probe ctx = { 0 };
ecs_set_ctx(world, &ctx, NULL);
ecs_entity_t e = ecs_new(world, 0);
ecs_add_pair(world, e, ecs_id(Rel), ecs_id(Position));
test_int(ctx.count, 1);
test_int(ctx.invoked, 1);
test_int(ctx.system, PairTrigger);
test_int(ctx.term_count, 1);
test_null(ctx.param);
test_int(ctx.e[0], e);
ecs_entity_t c = ctx.c[0][0];
ecs_entity_t hi = ECS_PAIR_FIRST(c);
ecs_entity_t lo = ECS_PAIR_SECOND(c);
test_int(hi, ecs_id(Rel));
test_int(lo, ecs_id(Position));
ecs_os_zeromem(&ctx);
ecs_add_pair(world, e, ecs_id(Rel), ecs_id(Velocity));
test_int(ctx.count, 1);
test_int(ctx.invoked, 1);
test_int(ctx.system, PairTrigger);
test_int(ctx.term_count, 1);
test_null(ctx.param);
test_int(ctx.e[0], e);
c = ctx.c[0][0];
hi = ECS_PAIR_FIRST(c);
lo = ECS_PAIR_SECOND(c);
test_int(hi, ecs_id(Rel));
test_int(lo, ecs_id(Velocity));
ecs_fini(world);
}
void Pairs_on_add_pair_tag(void) {
ecs_world_t *world = ecs_mini();
ECS_COMPONENT(world, Position);
ECS_TAG(world, Rel);
ECS_OBSERVER(world, PairTrigger, EcsOnAdd, (Rel, Position));
Probe ctx = { 0 };
ecs_set_ctx(world, &ctx, NULL);
ecs_entity_t e = ecs_new(world, 0);
ecs_add_pair(world, e, Rel, ecs_id(Position));
test_int(ctx.count, 1);
test_int(ctx.invoked, 1);
test_int(ctx.system, PairTrigger);
test_int(ctx.term_count, 1);
test_null(ctx.param);
test_int(ctx.e[0], e);
ecs_entity_t c = ctx.c[0][0];
ecs_entity_t hi = ECS_PAIR_FIRST(c);
ecs_entity_t lo = ECS_PAIR_SECOND(c);
test_int(hi, Rel);
test_int(lo, ecs_id(Position));
ecs_fini(world);
}
void Pairs_on_remove_pair(void) {
ecs_world_t *world = ecs_mini();
ECS_COMPONENT(world, Position);
ECS_COMPONENT(world, Velocity);
ECS_COMPONENT(world, Rel);
ECS_OBSERVER(world, PairTrigger, EcsOnRemove, (Rel, *));
Probe ctx = { 0 };
ecs_set_ctx(world, &ctx, NULL);
ecs_entity_t e = ecs_new(world, 0);
ecs_add_pair(world, e, ecs_id(Rel), ecs_id(Position));
ecs_add_pair(world, e, ecs_id(Rel), ecs_id(Velocity));
test_int(ctx.count, 0);
ecs_remove_pair(world, e, ecs_id(Rel), ecs_id(Position));
test_int(ctx.count, 1);
test_int(ctx.invoked, 1);
test_int(ctx.system, PairTrigger);
test_int(ctx.term_count, 1);
test_null(ctx.param);
test_int(ctx.e[0], e);
ecs_entity_t c = ctx.c[0][0];
ecs_entity_t hi = ECS_PAIR_FIRST(c);
ecs_entity_t lo = ECS_PAIR_SECOND(c);
test_int(hi, ecs_id(Rel));
test_int(lo, ecs_id(Position));
ecs_os_zeromem(&ctx);
ecs_remove_pair(world, e, ecs_id(Rel), ecs_id(Velocity));
test_int(ctx.count, 1);
test_int(ctx.invoked, 1);
test_int(ctx.system, PairTrigger);
test_int(ctx.term_count, 1);
test_null(ctx.param);
test_int(ctx.e[0], e);
c = ctx.c[0][0];
hi = ECS_PAIR_FIRST(c);
lo = ECS_PAIR_SECOND(c);
test_int(hi, ecs_id(Rel));
test_int(lo, ecs_id(Velocity));
ecs_fini(world);
}
void Pairs_on_remove_pair_tag(void) {
ecs_world_t *world = ecs_mini();
ECS_COMPONENT(world, Position);
ECS_TAG(world, Rel);
ECS_OBSERVER(world, PairTrigger, EcsOnRemove, (Rel, Position));
Probe ctx = { 0 };
ecs_set_ctx(world, &ctx, NULL);
ecs_entity_t e = ecs_new(world, 0);
ecs_add_pair(world, e, Rel, ecs_id(Position));
test_int(ctx.count, 0);
ecs_remove_pair(world, e, Rel, ecs_id(Position));
test_int(ctx.count, 1);
test_int(ctx.invoked, 1);
test_int(ctx.system, PairTrigger);
test_int(ctx.term_count, 1);
test_null(ctx.param);
test_int(ctx.e[0], e);
ecs_entity_t c = ctx.c[0][0];
ecs_entity_t hi = ECS_PAIR_FIRST(c);
ecs_entity_t lo = ECS_PAIR_SECOND(c);
test_int(hi, Rel);
test_int(lo, ecs_id(Position));
ecs_fini(world);
}
void Pairs_on_remove_pair_on_delete(void) {
ecs_world_t *world = ecs_mini();
ECS_COMPONENT(world, Position);
ECS_COMPONENT(world, Velocity);
ECS_COMPONENT(world, Rel);
ECS_OBSERVER(world, PairTrigger, EcsOnRemove, (Rel, *));
Probe ctx = { 0 };
ecs_set_ctx(world, &ctx, NULL);
ecs_entity_t e = ecs_new(world, 0);
ecs_add_pair(world, e, ecs_id(Rel), ecs_id(Position));
ecs_add_pair(world, e, ecs_id(Rel), ecs_id(Velocity));
test_int(ctx.count, 0);
ecs_delete(world, e);
test_int(ctx.count, 2);
test_int(ctx.invoked, 2);
test_int(ctx.system, PairTrigger);
test_int(ctx.term_count, 1);
test_null(ctx.param);
test_int(ctx.e[0], e);
ecs_entity_t c = ctx.c[0][0];
ecs_entity_t hi = ECS_PAIR_FIRST(c);
ecs_entity_t lo = ECS_PAIR_SECOND(c);
test_int(hi, ecs_id(Rel));
test_int(lo, ecs_id(Position));
test_int(ctx.e[1], e);
c = ctx.c[1][0];
hi = ECS_PAIR_FIRST(c);
lo = ECS_PAIR_SECOND(c);
test_int(hi, ecs_id(Rel));
test_int(lo, ecs_id(Velocity));
ecs_fini(world);
}
static
void PairTriggerPosition(ecs_iter_t *it) {
PairTrigger(it);
}
static
void PairTriggerVelocity(ecs_iter_t *it) {
PairTrigger(it);
}
void Pairs_on_remove_pair_tag_on_delete(void) {
ecs_world_t *world = ecs_mini();
ECS_COMPONENT(world, Position);
ECS_COMPONENT(world, Velocity);
ECS_TAG(world, Rel);
ECS_OBSERVER(world, PairTriggerPosition, EcsOnRemove, (Rel, Position));
ECS_OBSERVER(world, PairTriggerVelocity, EcsOnRemove, (Rel, Velocity));
Probe ctx = { 0 };
ecs_set_ctx(world, &ctx, NULL);
ecs_entity_t e = ecs_new(world, 0);
ecs_add_pair(world, e, Rel, ecs_id(Position));
ecs_add_pair(world, e, Rel, ecs_id(Velocity));
test_int(ctx.count, 0);
ecs_delete(world, e);
test_int(ctx.count, 2);
test_int(ctx.invoked, 2);
test_int(ctx.system, PairTriggerVelocity);
test_int(ctx.term_count, 1);
test_null(ctx.param);
test_int(ctx.e[0], e);
ecs_entity_t c = ctx.c[0][0];
ecs_entity_t hi = ECS_PAIR_FIRST(c);
ecs_entity_t lo = ECS_PAIR_SECOND(c);
test_int(hi, Rel);
test_int(lo, ecs_id(Position));
test_int(ctx.e[1], e);
c = ctx.c[1][0];
hi = ECS_PAIR_FIRST(c);
lo = ECS_PAIR_SECOND(c);
test_int(hi, Rel);
test_int(lo, ecs_id(Velocity));
ecs_fini(world);
}
void Pairs_pair_w_component_query(void) {
ecs_world_t *world = ecs_mini();
ECS_COMPONENT(world, Position);
ECS_COMPONENT(world, Rel);
ecs_entity_t e = ecs_new(world, 0);
ecs_add_pair(world, e, ecs_id(Rel), ecs_id(Position));
ecs_query_t *q = ecs_query_new(world, "(Rel, Position)");
int32_t count = 0;
ecs_iter_t it = ecs_query_iter(world, q);
while (ecs_query_next(&it)) {
Rel *t = ecs_field(&it, Rel, 1);
test_assert(t != NULL);
int i;
for (i = 0; i < it.count; i ++) {
test_assert(it.entities[i] == e);
}
count += it.count;
}
test_assert(count == 1);
ecs_fini(world);
}
void Pairs_query_pair_or_component(void) {
ecs_world_t *world = ecs_mini();
ECS_COMPONENT(world, Position);
ECS_TAG(world, Rel);
ecs_entity_t e1 = ecs_new(world, 0);
ecs_add_pair(world, e1, Rel, ecs_id(Position));
ecs_entity_t e2 = ecs_new(world, Position);
ecs_query_t *q = ecs_query_new(world, "(Rel, Position) || Position");
int32_t count = 0;
ecs_iter_t it = ecs_query_iter(world, q);
while (ecs_query_next(&it)) {
int i;
for (i = 0; i < it.count; i ++) {
test_assert(it.entities[i] == e1 || it.entities[i] == e2);
}
count += it.count;
}
test_assert(count == 2);
ecs_fini(world);
}
void Pairs_query_pair_or_pair(void) {
ecs_world_t *world = ecs_mini();
ECS_COMPONENT(world, Position);
ECS_TAG(world, RelA);
ECS_TAG(world, RelB);
ecs_entity_t e1 = ecs_new(world, 0);
ecs_add_pair(world, e1, RelA, ecs_id(Position));
ecs_entity_t e2 = ecs_new(world, Position);
ecs_add_pair(world, e2, RelB, ecs_id(Position));
ecs_query_t *q = ecs_query_new(world, "(RelA, Position) || (RelB, Position)");
int32_t count = 0;
ecs_iter_t it = ecs_query_iter(world, q);
while (ecs_query_next(&it)) {
int i;
for (i = 0; i < it.count; i ++) {
test_assert(it.entities[i] == e1 || it.entities[i] == e2);
}
count += it.count;
}
test_int(count, 2);
ecs_fini(world);
}
void Pairs_query_not_pair(void) {
ecs_world_t *world = ecs_mini();
ECS_COMPONENT(world, Position);
ECS_TAG(world, Rel);
ecs_entity_t e1 = ecs_new(world, Position);
ecs_entity_t e2 = ecs_new(world, Position);
ecs_add_pair(world, e2, Rel, ecs_id(Position));
ecs_query_t *q = ecs_query_new(world, "!(Rel, Position), Position");
int32_t count = 0;
ecs_iter_t it = ecs_query_iter(world, q);
while (ecs_query_next(&it)) {
Position *t = ecs_field(&it, Position, 1);
test_assert(t == NULL);
Position *p = ecs_field(&it, Position, 2);
test_assert(p != NULL);
int i;
for (i = 0; i < it.count; i ++) {
test_assert(it.entities[i] == e1);
}
count += it.count;
}
test_assert(count == 1);
ecs_fini(world);
}
void Pairs_get_typeid_w_recycled_rel(void) {
ecs_world_t *world = ecs_mini();
ecs_entity_t o = ecs_new_id(world);
test_assert(o != 0);
ecs_entity_t dummy = ecs_new_id(world);
ecs_delete(world, dummy); // force recycle
// don't use ECS_COMPONENT, because it will try to get low ids first
ecs_entity_t pos = ecs_set(world, 0, EcsComponent, {1, 1});
test_assert(pos != 0);
test_assert((uint32_t)pos != pos); // ensure recycled
ecs_id_t pair = ecs_pair(pos, o);
ecs_entity_t tid = ecs_get_typeid(world, pair);
test_assert(tid != 0);
test_assert(tid == pos);
ecs_fini(world);
}
void Pairs_get_typeid_w_recycled_obj(void) {
ecs_world_t *world = ecs_mini();
ecs_entity_t r = ecs_new_id(world);
test_assert(r != 0);
ecs_entity_t dummy = ecs_new_id(world);
ecs_delete(world, dummy); // force recycle
// don't use ECS_COMPONENT, because it will try to get low ids first
ecs_entity_t pos = ecs_set(world, 0, EcsComponent, {1, 1});
test_assert(pos != 0);
test_assert((uint32_t)pos != pos); // ensure recycled
ecs_id_t pair = ecs_pair(r, pos);
ecs_entity_t tid = ecs_get_typeid(world, pair);
test_assert(tid != 0);
test_assert(tid == pos);
ecs_fini(world);
}
void Pairs_id_str_w_recycled_rel(void) {
ecs_world_t *world = ecs_mini();
ecs_entity_t o = ecs_set_name(world, 0, "o");
test_assert(o != 0);
ecs_entity_t dummy = ecs_new_id(world);
ecs_delete(world, dummy); // force recycle
ecs_entity_t r = ecs_set_name(world, 0, "r");
test_assert(r != 0);
test_assert((uint32_t)r != r); // ensure recycled
char *str = ecs_id_str(world, ecs_pair(r, o));
test_str(str, "(r,o)");
ecs_os_free(str);
ecs_fini(world);
}
void Pairs_id_str_w_recycled_obj(void) {
ecs_world_t *world = ecs_mini();
ecs_entity_t r = ecs_set_name(world, 0, "r");
test_assert(r != 0);
ecs_entity_t dummy = ecs_new_id(world);
ecs_delete(world, dummy); // force recycle
ecs_entity_t o = ecs_set_name(world, 0, "o");
test_assert(o != 0);
test_assert((uint32_t)o != o); // ensure recycled
char *str = ecs_id_str(world, ecs_pair(r, o));
test_str(str, "(r,o)");
ecs_os_free(str);
ecs_fini(world);
}
void Pairs_set_object_w_zero_sized_rel_comp(void) {
ecs_world_t *world = ecs_mini();
ecs_entity_t r = ecs_set(world, 0, EcsComponent, {0});
ECS_COMPONENT(world, Position);
ecs_entity_t e = ecs_set_pair_object(world, 0, r, Position, {10, 20});
const Position *p = ecs_get_pair_object(world, e, r, Position);
test_assert(p != NULL);
test_int(p->x, 10);
test_int(p->y, 20);
ecs_fini(world);
}
void Pairs_dsl_pair(void) {
ecs_world_t *world = ecs_mini();
ECS_TAG(world, Rel);
ECS_TAG(world, Rel_2);
ECS_TAG(world, Obj);
ECS_TAG(world, Obj_2);
ecs_query_t *q = ecs_query_init(world, &(ecs_query_desc_t){
.filter.expr = "(Rel, Obj)"
});
test_assert(q != NULL);
ecs_entity_t e1 = ecs_entity_init(world, &(ecs_entity_desc_t){
.add = {ecs_pair(Rel, Obj)} });
test_assert(e1 != 0);
ecs_entity_t e2 = ecs_entity_init(world, &(ecs_entity_desc_t){
.add = {ecs_pair(Rel, Obj_2)} });
test_assert(e2 != 0);
ecs_entity_t e3 = ecs_entity_init(world, &(ecs_entity_desc_t){
.add = {ecs_pair(Rel_2, Obj)} });
test_assert(e3 != 0);
ecs_entity_t e4 = ecs_entity_init(world, &(ecs_entity_desc_t){
.add = {ecs_pair(Rel_2, Obj_2)} });
test_assert(e4 != 0);
ecs_iter_t it = ecs_query_iter(world, q);
test_bool(ecs_query_next(&it), true);
test_int(it.count, 1);
test_int(it.entities[0], e1);
test_int(ecs_field_id(&it, 1), ecs_pair(Rel, Obj));
test_bool(ecs_query_next(&it), false);
ecs_fini(world);
}
void Pairs_dsl_pair_w_pred_wildcard(void) {
ecs_world_t *world = ecs_mini();
ECS_TAG(world, Rel);
ECS_TAG(world, Rel_2);
ECS_TAG(world, Obj);
ECS_TAG(world, Obj_2);
ecs_query_t *q = ecs_query_init(world, &(ecs_query_desc_t){
.filter.expr = "(*, Obj)"
});
test_assert(q != NULL);
ecs_entity_t e1 = ecs_entity_init(world, &(ecs_entity_desc_t){
.add = {ecs_pair(Rel, Obj)} });
test_assert(e1 != 0);
ecs_entity_t e2 = ecs_entity_init(world, &(ecs_entity_desc_t){
.add = {ecs_pair(Rel, Obj_2)} });
test_assert(e2 != 0);
ecs_entity_t e3 = ecs_entity_init(world, &(ecs_entity_desc_t){
.add = {ecs_pair(Rel_2, Obj)} });
test_assert(e3 != 0);
ecs_entity_t e4 = ecs_entity_init(world, &(ecs_entity_desc_t){
.add = {ecs_pair(Rel_2, Obj_2)} });
test_assert(e4 != 0);
ecs_iter_t it = ecs_query_iter(world, q);
test_bool(ecs_query_next(&it), true);
test_int(it.count, 1);
test_int(it.entities[0], e1);
test_int(ecs_field_id(&it, 1), ecs_pair(Rel, Obj));
test_bool(ecs_query_next(&it), true);
test_int(it.count, 1);
test_int(it.entities[0], e3);
test_int(ecs_field_id(&it, 1), ecs_pair(Rel_2, Obj));
test_bool(ecs_query_next(&it), false);
ecs_fini(world);
}
void Pairs_dsl_pair_w_obj_wildcard(void) {
ecs_world_t *world = ecs_mini();
ECS_TAG(world, Rel);
ECS_TAG(world, Rel_2);
ECS_TAG(world, Obj);
ECS_TAG(world, Obj_2);
ecs_query_t *q = ecs_query_init(world, &(ecs_query_desc_t){
.filter.expr = "(Rel_2, *)"
});
test_assert(q != NULL);
ecs_entity_t e1 = ecs_entity_init(world, &(ecs_entity_desc_t){
.add = {ecs_pair(Rel, Obj)} });
test_assert(e1 != 0);
ecs_entity_t e2 = ecs_entity_init(world, &(ecs_entity_desc_t){
.add = {ecs_pair(Rel, Obj_2)} });
test_assert(e2 != 0);
ecs_entity_t e3 = ecs_entity_init(world, &(ecs_entity_desc_t){
.add = {ecs_pair(Rel_2, Obj)} });
test_assert(e3 != 0);
ecs_entity_t e4 = ecs_entity_init(world, &(ecs_entity_desc_t){
.add = {ecs_pair(Rel_2, Obj_2)} });
test_assert(e4 != 0);
ecs_iter_t it = ecs_query_iter(world, q);
test_bool(ecs_query_next(&it), true);
test_int(it.count, 1);
test_int(it.entities[0], e3);
test_int(ecs_field_id(&it, 1), ecs_pair(Rel_2, Obj));
test_bool(ecs_query_next(&it), true);
test_int(it.count, 1);
test_int(it.entities[0], e4);
test_int(ecs_field_id(&it, 1), ecs_pair(Rel_2, Obj_2));
test_bool(ecs_query_next(&it), false);
ecs_fini(world);
}
void Pairs_dsl_pair_w_both_wildcard(void) {
ecs_world_t *world = ecs_mini();
ECS_TAG(world, Rel);
ECS_TAG(world, Rel_2);
ECS_TAG(world, Obj);
ECS_TAG(world, Obj_2);
ECS_TAG(world, Tag);
ecs_query_t *q = ecs_query_init(world, &(ecs_query_desc_t){
.filter.expr = "(*, *), Tag" // add Tag or we'd match builtin entities
});
test_assert(q != NULL);
ecs_entity_t e1 = ecs_entity_init(world, &(ecs_entity_desc_t){
.add = {ecs_pair(Rel, Obj), Tag} });
test_assert(e1 != 0);
ecs_entity_t e2 = ecs_entity_init(world, &(ecs_entity_desc_t){
.add = {ecs_pair(Rel, Obj_2), Tag} });
test_assert(e2 != 0);
ecs_entity_t e3 = ecs_entity_init(world, &(ecs_entity_desc_t){
.add = {ecs_pair(Rel_2, Obj), Tag} });
test_assert(e3 != 0);
ecs_entity_t e4 = ecs_entity_init(world, &(ecs_entity_desc_t){
.add = {ecs_pair(Rel_2, Obj_2), Tag} });
test_assert(e4 != 0);
ecs_iter_t it = ecs_query_iter(world, q);
test_bool(ecs_query_next(&it), true);
test_int(it.count, 1);
test_int(it.entities[0], e1);
test_int(ecs_field_id(&it, 1), ecs_pair(Rel, Obj));
test_bool(ecs_query_next(&it), true);
test_int(it.count, 1);
test_int(it.entities[0], e2);
test_int(ecs_field_id(&it, 1), ecs_pair(Rel, Obj_2));
test_bool(ecs_query_next(&it), true);
test_int(it.count, 1);
test_int(it.entities[0], e3);
test_int(ecs_field_id(&it, 1), ecs_pair(Rel_2, Obj));
test_bool(ecs_query_next(&it), true);
test_int(it.count, 1);
test_int(it.entities[0], e4);
test_int(ecs_field_id(&it, 1), ecs_pair(Rel_2, Obj_2));
test_bool(ecs_query_next(&it), false);
ecs_fini(world);
}
void Pairs_dsl_pair_w_explicit_subj_this(void) {
ecs_world_t *world = ecs_mini();
ECS_TAG(world, Rel);
ECS_TAG(world, Rel_2);
ECS_TAG(world, Obj);
ECS_TAG(world, Obj_2);
ecs_query_t *q = ecs_query_init(world, &(ecs_query_desc_t){
.filter.expr = "Rel($This, Obj)"
});
test_assert(q != NULL);
ecs_entity_t e1 = ecs_entity_init(world, &(ecs_entity_desc_t){
.add = {ecs_pair(Rel, Obj)} });
test_assert(e1 != 0);
ecs_entity_t e2 = ecs_entity_init(world, &(ecs_entity_desc_t){
.add = {ecs_pair(Rel, Obj_2)} });
test_assert(e2 != 0);
ecs_entity_t e3 = ecs_entity_init(world, &(ecs_entity_desc_t){
.add = {ecs_pair(Rel_2, Obj)} });
test_assert(e3 != 0);
ecs_entity_t e4 = ecs_entity_init(world, &(ecs_entity_desc_t){
.add = {ecs_pair(Rel_2, Obj_2)} });
test_assert(e4 != 0);
ecs_iter_t it = ecs_query_iter(world, q);
test_bool(ecs_query_next(&it), true);
test_int(it.count, 1);
test_int(it.entities[0], e1);
test_int(ecs_field_id(&it, 1), ecs_pair(Rel, Obj));
test_bool(ecs_query_next(&it), false);
ecs_fini(world);
}
void Pairs_dsl_pair_w_explicit_subj(void) {
ecs_world_t *world = ecs_mini();
ECS_TAG(world, Rel);
ECS_TAG(world, Rel_2);
ECS_TAG(world, Obj);
ECS_TAG(world, Obj_2);
ECS_TAG(world, Tag);
ecs_entity_t Subj = ecs_entity_init(world, &(ecs_entity_desc_t){
.name = "Subj", .add = {ecs_pair(Rel, Obj)} });
test_assert(Subj != 0);
ecs_query_t *q = ecs_query_init(world, &(ecs_query_desc_t){
.filter.expr = "Rel(Subj, Obj), Tag"
});
test_assert(q != NULL);
ecs_entity_t e1 = ecs_entity_init(world, &(ecs_entity_desc_t){
.add = {ecs_pair(Rel, Obj)} });
test_assert(e1 != 0);
ecs_entity_t e2 = ecs_entity_init(world, &(ecs_entity_desc_t){
.add = {ecs_pair(Rel, Obj_2)} });
test_assert(e2 != 0);
ecs_entity_t e3 = ecs_entity_init(world, &(ecs_entity_desc_t){
.add = {ecs_pair(Rel_2, Obj)} });
test_assert(e3 != 0);
ecs_entity_t e4 = ecs_entity_init(world, &(ecs_entity_desc_t){
.add = {ecs_pair(Rel_2, Obj_2), Tag} });
test_assert(e4 != 0);
ecs_iter_t it = ecs_query_iter(world, q);
test_bool(ecs_query_next(&it), true);
test_int(it.count, 1);
test_int(it.entities[0], e4);
test_int(ecs_field_id(&it, 1), ecs_pair(Rel, Obj));
test_int(ecs_field_src(&it, 1), Subj);
test_bool(ecs_query_next(&it), false);
ecs_fini(world);
}
void Pairs_api_pair(void) {
ecs_world_t *world = ecs_mini();
ECS_TAG(world, Rel);
ECS_TAG(world, Rel_2);
ECS_TAG(world, Obj);
ECS_TAG(world, Obj_2);
ecs_query_t *q = ecs_query_init(world, &(ecs_query_desc_t){
.filter.terms = {{ecs_pair(Rel, Obj)}}
});
test_assert(q != NULL);
ecs_entity_t e1 = ecs_entity_init(world, &(ecs_entity_desc_t){
.add = {ecs_pair(Rel, Obj)} });
test_assert(e1 != 0);
ecs_entity_t e2 = ecs_entity_init(world, &(ecs_entity_desc_t){
.add = {ecs_pair(Rel, Obj_2)} });
test_assert(e2 != 0);
ecs_entity_t e3 = ecs_entity_init(world, &(ecs_entity_desc_t){
.add = {ecs_pair(Rel_2, Obj)} });
test_assert(e3 != 0);
ecs_entity_t e4 = ecs_entity_init(world, &(ecs_entity_desc_t){
.add = {ecs_pair(Rel_2, Obj_2)} });
test_assert(e4 != 0);
ecs_iter_t it = ecs_query_iter(world, q);
test_bool(ecs_query_next(&it), true);
test_int(it.count, 1);
test_int(it.entities[0], e1);
test_int(ecs_field_id(&it, 1), ecs_pair(Rel, Obj));
test_bool(ecs_query_next(&it), false);
ecs_fini(world);
}
void Pairs_api_pair_w_pred_wildcard(void) {
ecs_world_t *world = ecs_mini();
ECS_TAG(world, Rel);
ECS_TAG(world, Rel_2);
ECS_TAG(world, Obj);
ECS_TAG(world, Obj_2);
ecs_query_t *q = ecs_query_init(world, &(ecs_query_desc_t){
.filter.terms = {{ecs_pair(EcsWildcard, Obj)}}
});
test_assert(q != NULL);
ecs_entity_t e1 = ecs_entity_init(world, &(ecs_entity_desc_t){
.add = {ecs_pair(Rel, Obj)} });
test_assert(e1 != 0);
ecs_entity_t e2 = ecs_entity_init(world, &(ecs_entity_desc_t){
.add = {ecs_pair(Rel, Obj_2)} });
test_assert(e2 != 0);
ecs_entity_t e3 = ecs_entity_init(world, &(ecs_entity_desc_t){
.add = {ecs_pair(Rel_2, Obj)} });
test_assert(e3 != 0);
ecs_entity_t e4 = ecs_entity_init(world, &(ecs_entity_desc_t){
.add = {ecs_pair(Rel_2, Obj_2)} });
test_assert(e4 != 0);
ecs_iter_t it = ecs_query_iter(world, q);
test_bool(ecs_query_next(&it), true);
test_int(it.count, 1);
test_int(it.entities[0], e1);
test_int(ecs_field_id(&it, 1), ecs_pair(Rel, Obj));
test_bool(ecs_query_next(&it), true);
test_int(it.count, 1);
test_int(it.entities[0], e3);
test_int(ecs_field_id(&it, 1), ecs_pair(Rel_2, Obj));
test_bool(ecs_query_next(&it), false);
ecs_fini(world);
}
void Pairs_api_pair_w_obj_wildcard(void) {
ecs_world_t *world = ecs_mini();
ECS_TAG(world, Rel);
ECS_TAG(world, Rel_2);
ECS_TAG(world, Obj);
ECS_TAG(world, Obj_2);
ecs_query_t *q = ecs_query_init(world, &(ecs_query_desc_t){
.filter.terms = {{ecs_pair(Rel_2, EcsWildcard)}}
});
test_assert(q != NULL);
ecs_entity_t e1 = ecs_entity_init(world, &(ecs_entity_desc_t){
.add = {ecs_pair(Rel, Obj)} });
test_assert(e1 != 0);
ecs_entity_t e2 = ecs_entity_init(world, &(ecs_entity_desc_t){
.add = {ecs_pair(Rel, Obj_2)} });
test_assert(e2 != 0);
ecs_entity_t e3 = ecs_entity_init(world, &(ecs_entity_desc_t){
.add = {ecs_pair(Rel_2, Obj)} });
test_assert(e3 != 0);
ecs_entity_t e4 = ecs_entity_init(world, &(ecs_entity_desc_t){
.add = {ecs_pair(Rel_2, Obj_2)} });
test_assert(e4 != 0);
ecs_iter_t it = ecs_query_iter(world, q);
test_bool(ecs_query_next(&it), true);
test_int(it.count, 1);
test_int(it.entities[0], e3);
test_int(ecs_field_id(&it, 1), ecs_pair(Rel_2, Obj));
test_bool(ecs_query_next(&it), true);
test_int(it.count, 1);
test_int(it.entities[0], e4);
test_int(ecs_field_id(&it, 1), ecs_pair(Rel_2, Obj_2));
test_bool(ecs_query_next(&it), false);
ecs_fini(world);
}
void Pairs_api_pair_w_both_wildcard(void) {
ecs_world_t *world = ecs_mini();
ECS_TAG(world, Rel);
ECS_TAG(world, Rel_2);
ECS_TAG(world, Obj);
ECS_TAG(world, Obj_2);
ECS_TAG(world, Tag);
ecs_query_t *q = ecs_query_init(world, &(ecs_query_desc_t){
// add Tag or we'd match builtin entities
.filter.terms = {{ecs_pair(EcsWildcard, EcsWildcard)}, {Tag}}
});
test_assert(q != NULL);
ecs_entity_t e1 = ecs_entity_init(world, &(ecs_entity_desc_t){
.add = {ecs_pair(Rel, Obj), Tag} });
test_assert(e1 != 0);
ecs_entity_t e2 = ecs_entity_init(world, &(ecs_entity_desc_t){
.add = {ecs_pair(Rel, Obj_2), Tag} });
test_assert(e2 != 0);
ecs_entity_t e3 = ecs_entity_init(world, &(ecs_entity_desc_t){
.add = {ecs_pair(Rel_2, Obj), Tag} });
test_assert(e3 != 0);
ecs_entity_t e4 = ecs_entity_init(world, &(ecs_entity_desc_t){
.add = {ecs_pair(Rel_2, Obj_2), Tag} });
test_assert(e4 != 0);
ecs_iter_t it = ecs_query_iter(world, q);
test_bool(ecs_query_next(&it), true);
test_int(it.count, 1);
test_int(it.entities[0], e1);
test_int(ecs_field_id(&it, 1), ecs_pair(Rel, Obj));
test_bool(ecs_query_next(&it), true);
test_int(it.count, 1);
test_int(it.entities[0], e2);
test_int(ecs_field_id(&it, 1), ecs_pair(Rel, Obj_2));
test_bool(ecs_query_next(&it), true);
test_int(it.count, 1);
test_int(it.entities[0], e3);
test_int(ecs_field_id(&it, 1), ecs_pair(Rel_2, Obj));
test_bool(ecs_query_next(&it), true);
test_int(it.count, 1);
test_int(it.entities[0], e4);
test_int(ecs_field_id(&it, 1), ecs_pair(Rel_2, Obj_2));
test_bool(ecs_query_next(&it), false);
ecs_fini(world);
}
void Pairs_api_pair_w_explicit_subj_this(void) {
ecs_world_t *world = ecs_mini();
ECS_TAG(world, Rel);
ECS_TAG(world, Rel_2);
ECS_TAG(world, Obj);
ECS_TAG(world, Obj_2);
ecs_query_t *q = ecs_query_init(world, &(ecs_query_desc_t){
.filter.terms = {
{ ecs_pair(Rel, Obj), .src.id = EcsThis }
}
});
test_assert(q != NULL);
ecs_entity_t e1 = ecs_entity_init(world, &(ecs_entity_desc_t){
.add = {ecs_pair(Rel, Obj)} });
test_assert(e1 != 0);
ecs_entity_t e2 = ecs_entity_init(world, &(ecs_entity_desc_t){
.add = {ecs_pair(Rel, Obj_2)} });
test_assert(e2 != 0);
ecs_entity_t e3 = ecs_entity_init(world, &(ecs_entity_desc_t){
.add = {ecs_pair(Rel_2, Obj)} });
test_assert(e3 != 0);
ecs_entity_t e4 = ecs_entity_init(world, &(ecs_entity_desc_t){
.add = {ecs_pair(Rel_2, Obj_2)} });
test_assert(e4 != 0);
ecs_iter_t it = ecs_query_iter(world, q);
test_bool(ecs_query_next(&it), true);
test_int(it.count, 1);
test_int(it.entities[0], e1);
test_int(ecs_field_id(&it, 1), ecs_pair(Rel, Obj));
test_bool(ecs_query_next(&it), false);
ecs_fini(world);
}
void Pairs_api_pair_w_explicit_subj(void) {
ecs_world_t *world = ecs_mini();
ECS_TAG(world, Rel);
ECS_TAG(world, Rel_2);
ECS_TAG(world, Obj);
ECS_TAG(world, Obj_2);
ECS_TAG(world, Tag);
ecs_entity_t Subj = ecs_entity_init(world, &(ecs_entity_desc_t){
.name = "Subj", .add = {ecs_pair(Rel, Obj)} });
test_assert(Subj != 0);
ecs_query_t *q = ecs_query_init(world, &(ecs_query_desc_t){
.filter.terms = {{ecs_pair(Rel, Obj), .src.id = Subj}, {Tag}}
});
test_assert(q != NULL);
ecs_entity_t e1 = ecs_entity_init(world, &(ecs_entity_desc_t){
.add = {ecs_pair(Rel, Obj)} });
test_assert(e1 != 0);
ecs_entity_t e2 = ecs_entity_init(world, &(ecs_entity_desc_t){
.add = {ecs_pair(Rel, Obj_2)} });
test_assert(e2 != 0);
ecs_entity_t e3 = ecs_entity_init(world, &(ecs_entity_desc_t){
.add = {ecs_pair(Rel_2, Obj)} });
test_assert(e3 != 0);
ecs_entity_t e4 = ecs_entity_init(world, &(ecs_entity_desc_t){
.add = {ecs_pair(Rel_2, Obj_2), Tag} });
test_assert(e4 != 0);
ecs_iter_t it = ecs_query_iter(world, q);
test_bool(ecs_query_next(&it), true);
test_int(it.count, 1);
test_int(it.entities[0], e4);
test_int(ecs_field_id(&it, 1), ecs_pair(Rel, Obj));
test_int(ecs_field_src(&it, 1), Subj);
test_bool(ecs_query_next(&it), false);
ecs_fini(world);
}
void Pairs_typeid_from_tag(void) {
ecs_world_t *world = ecs_mini();
ecs_entity_t tag = ecs_new_id(world);
test_assert(tag != 0);
ecs_entity_t id = ecs_get_typeid(world, tag);
test_assert(id == 0);
ecs_fini(world);
}
void Pairs_typeid_from_component(void) {
ecs_world_t *world = ecs_mini();
ECS_COMPONENT(world, Rel);
ecs_id_t rel_id = ecs_id(Rel);
test_assert(rel_id != 0);
ecs_entity_t id = ecs_get_typeid(world, rel_id);
test_assert(id != 0);
test_assert(id == rel_id);
ecs_fini(world);
}
void Pairs_typeid_from_pair(void) {
ecs_world_t *world = ecs_mini();
ecs_entity_t rel_id = ecs_new_id(world);
test_assert(rel_id != 0);
ecs_entity_t obj_id = ecs_new_id(world);
test_assert(obj_id != 0);
ecs_id_t pair_id = ecs_pair(rel_id, obj_id);
ecs_entity_t id = ecs_get_typeid(world, pair_id);
test_assert(id == 0);
ecs_fini(world);
}
void Pairs_typeid_from_pair_w_rel_type(void) {
ecs_world_t *world = ecs_mini();
ECS_COMPONENT(world, Rel);
ecs_id_t rel_id = ecs_id(Rel);
test_assert(rel_id != 0);
ecs_entity_t obj_id = ecs_new_id(world);
test_assert(obj_id != 0);
ecs_id_t pair_id = ecs_pair(rel_id, obj_id);
ecs_entity_t id = ecs_get_typeid(world, pair_id);
test_assert(id != 0);
test_assert(id == rel_id);
ecs_fini(world);
}
void Pairs_typeid_from_pair_w_obj_type(void) {
ecs_world_t *world = ecs_mini();
ECS_COMPONENT(world, Obj);
ecs_id_t obj_id = ecs_id(Obj);
test_assert(obj_id != 0);
ecs_entity_t rel_id = ecs_new_id(world);
test_assert(rel_id != 0);
ecs_id_t pair_id = ecs_pair(rel_id, obj_id);
ecs_entity_t id = ecs_get_typeid(world, pair_id);
test_assert(id != 0);
test_assert(id == obj_id);
ecs_fini(world);
}
void Pairs_typeid_from_pair_w_rel_obj_type(void) {
ecs_world_t *world = ecs_mini();
ECS_COMPONENT(world, Rel);
ecs_id_t rel_id = ecs_id(Rel);
test_assert(rel_id != 0);
ECS_COMPONENT(world, Obj);
ecs_id_t obj_id = ecs_id(Obj);
test_assert(obj_id != 0);
ecs_id_t pair_id = ecs_pair(rel_id, obj_id);
ecs_entity_t id = ecs_get_typeid(world, pair_id);
test_assert(id != 0);
test_assert(id == rel_id);
ecs_fini(world);
}
void Pairs_typeid_from_pair_w_rel_0_obj_type(void) {
ecs_world_t *world = ecs_mini();
ecs_id_t rel_id = ecs_set(world, 0, EcsComponent, {0});
test_assert(rel_id != 0);
ECS_COMPONENT(world, Obj);
ecs_id_t obj_id = ecs_id(Obj);
test_assert(obj_id != 0);
ecs_id_t pair_id = ecs_pair(rel_id, obj_id);
ecs_entity_t id = ecs_get_typeid(world, pair_id);
test_assert(id != 0);
test_assert(id == obj_id);
ecs_fini(world);
}
void Pairs_typeid_from_pair_w_rel_obj_0_type(void) {
ecs_world_t *world = ecs_mini();
ECS_COMPONENT(world, Rel);
ecs_id_t rel_id = ecs_id(Rel);
test_assert(rel_id != 0);
ecs_id_t obj_id = ecs_set(world, 0, EcsComponent, {0});
test_assert(obj_id != 0);
ecs_id_t pair_id = ecs_pair(rel_id, obj_id);
ecs_entity_t id = ecs_get_typeid(world, pair_id);
test_assert(id != 0);
test_assert(id == rel_id);
ecs_fini(world);
}
void Pairs_typeid_from_pair_w_rel_0_obj_0_type(void) {
ecs_world_t *world = ecs_mini();
ecs_id_t rel_id = ecs_set(world, 0, EcsComponent, {0});
test_assert(rel_id != 0);
ecs_id_t obj_id = ecs_set(world, 0, EcsComponent, {0});
test_assert(obj_id != 0);
ecs_id_t pair_id = ecs_pair(rel_id, obj_id);
ecs_entity_t id = ecs_get_typeid(world, pair_id);
test_assert(id == 0);
ecs_fini(world);
}
void Pairs_typeid_from_pair_with_0_obj(void) {
ecs_world_t *world = ecs_mini();
ecs_id_t pair_id = ecs_pair(EcsChildOf, 0);
ecs_entity_t id = ecs_get_typeid(world, pair_id);
test_assert(id == 0);
ecs_fini(world);
}
void Pairs_typeid_from_pair_w_override(void) {
ecs_world_t *world = ecs_mini();
ECS_COMPONENT(world, Rel);
ecs_id_t rel_id = ecs_id(Rel);
test_assert(rel_id != 0);
ecs_entity_t obj_id = ecs_new_id(world);
test_assert(obj_id != 0);
ecs_id_t pair_id = ECS_OVERRIDE | ecs_pair(rel_id, obj_id);
ecs_entity_t id = ecs_get_typeid(world, pair_id);
test_assert(id == 0);
ecs_fini(world);
}
void Pairs_typeid_from_pair_w_toggle(void) {
ecs_world_t *world = ecs_mini();
ECS_COMPONENT(world, Rel);
ecs_id_t rel_id = ecs_id(Rel);
test_assert(rel_id != 0);
ecs_entity_t obj_id = ecs_new_id(world);
test_assert(obj_id != 0);
ecs_id_t pair_id = ECS_TOGGLE | ecs_pair(rel_id, obj_id);
ecs_entity_t id = ecs_get_typeid(world, pair_id);
test_assert(id == 0);
ecs_fini(world);
}
void Pairs_tag_pair_w_rel_comp(void) {
ecs_world_t *world = ecs_mini();
ECS_COMPONENT(world, Position);
ECS_TAG(world, Obj);
ecs_add_id(world, ecs_id(Position), EcsTag);
ecs_entity_t e = ecs_new_id(world);
ecs_id_t pair_id = ecs_pair(ecs_id(Position), Obj);
ecs_add_id(world, e, pair_id);
ecs_entity_t id = ecs_get_typeid(world, pair_id);
test_assert(id == 0);
ecs_fini(world);
}
void Pairs_tag_pair_w_obj_comp(void) {
ecs_world_t *world = ecs_mini();
ECS_TAG(world, Rel);
ECS_COMPONENT(world, Position);
ecs_add_id(world, Rel, EcsTag);
ecs_entity_t e = ecs_new_id(world);
ecs_id_t pair_id = ecs_pair(Rel, ecs_id(Position));
ecs_add_id(world, e, pair_id);
ecs_entity_t id = ecs_get_typeid(world, pair_id);
test_assert(id == 0);
ecs_fini(world);
}
void Pairs_tag_pair_w_rel_obj_comp(void) {
ecs_world_t *world = ecs_mini();
ECS_COMPONENT(world, Position);
ECS_COMPONENT(world, Velocity);
ecs_add_id(world, ecs_id(Position), EcsTag);
ecs_entity_t e = ecs_new_id(world);
ecs_id_t pair_id = ecs_pair(ecs_id(Position), ecs_id(Velocity));
ecs_add_id(world, e, pair_id);
ecs_entity_t id = ecs_get_typeid(world, pair_id);
test_assert(id == 0);
ecs_fini(world);
}
void Pairs_get_tag_pair_w_rel_comp(void) {
install_test_abort();
ecs_world_t *world = ecs_mini();
ECS_COMPONENT(world, Position);
ECS_TAG(world, Obj);
ecs_add_id(world, ecs_id(Position), EcsTag);
ecs_entity_t e = ecs_new_id(world);
ecs_id_t pair_id = ecs_pair(ecs_id(Position), Obj);
ecs_add_id(world, e, pair_id);
test_expect_abort();
ecs_get_id(world, e, pair_id);
}
void Pairs_get_tag_pair_w_obj_comp(void) {
install_test_abort();
ecs_world_t *world = ecs_mini();
ECS_COMPONENT(world, Position);
ECS_COMPONENT(world, Velocity);
ecs_add_id(world, ecs_id(Position), EcsTag);
ecs_entity_t e = ecs_new_id(world);
ecs_id_t pair_id = ecs_pair(ecs_id(Position), ecs_id(Velocity));
ecs_add_id(world, e, pair_id);
test_expect_abort();
ecs_get_id(world, e, pair_id);
}
void Pairs_get_tag_pair_w_rel_obj_comp(void) {
install_test_abort();
ecs_world_t *world = ecs_mini();
ECS_COMPONENT(world, Position);
ECS_COMPONENT(world, Velocity);
ecs_add_id(world, ecs_id(Position), EcsTag);
ecs_entity_t e = ecs_new_id(world);
ecs_id_t pair_id = ecs_pair(ecs_id(Position), ecs_id(Velocity));
ecs_add_id(world, e, pair_id);
test_expect_abort();
ecs_get_id(world, e, pair_id);
}
void Pairs_tag_pair_w_childof_w_comp(void) {
ecs_world_t *world = ecs_mini();
ECS_COMPONENT(world, Position);
ecs_entity_t e = ecs_new_id(world);
ecs_id_t pair_id = ecs_pair(EcsChildOf, ecs_id(Position));
ecs_add_id(world, e, pair_id);
ecs_entity_t id = ecs_get_typeid(world, pair_id);
test_assert(id == 0);
ecs_fini(world);
}
void Pairs_tag_pair_w_isa_w_comp(void) {
ecs_world_t *world = ecs_mini();
ECS_COMPONENT(world, Position);
ecs_entity_t e = ecs_new_id(world);
ecs_id_t pair_id = ecs_pair(EcsIsA, ecs_id(Position));
ecs_add_id(world, e, pair_id);
ecs_entity_t id = ecs_get_typeid(world, pair_id);
test_assert(id == 0);
ecs_fini(world);
}
void Pairs_get_1_target(void) {
ecs_world_t *world = ecs_mini();
ecs_entity_t e = ecs_new_id(world);
ecs_entity_t rel = ecs_new_id(world);
ecs_entity_t obj = ecs_new_id(world);
ecs_add_pair(world, e, rel, obj);
test_assert(ecs_has_pair(world, e, rel, obj));
test_assert(ecs_get_target(world, e, rel, 0) == obj);
ecs_fini(world);
}
void Pairs_get_1_target_not_found(void) {
ecs_world_t *world = ecs_mini();
ecs_entity_t e = ecs_new_id(world);
ecs_entity_t rel = ecs_new_id(world);
test_assert(ecs_get_target(world, e, rel, 0) == 0);
ecs_fini(world);
}
void Pairs_get_n_targets(void) {
ecs_world_t *world = ecs_mini();
ecs_entity_t e = ecs_new_id(world);
ecs_entity_t rel = ecs_new_id(world);
ecs_entity_t obj_1 = ecs_new_id(world);
ecs_entity_t obj_2 = ecs_new_id(world);
ecs_entity_t obj_3 = ecs_new_id(world);
ecs_add_pair(world, e, rel, obj_1);
ecs_add_pair(world, e, rel, obj_2);
ecs_add_pair(world, e, rel, obj_3);
test_assert(ecs_has_pair(world, e, rel, obj_1));
test_assert(ecs_has_pair(world, e, rel, obj_2));
test_assert(ecs_has_pair(world, e, rel, obj_3));
test_assert(ecs_get_target(world, e, rel, 0) == obj_1);
test_assert(ecs_get_target(world, e, rel, 1) == obj_2);
test_assert(ecs_get_target(world, e, rel, 2) == obj_3);
test_assert(ecs_get_target(world, e, rel, 3) == 0);
ecs_fini(world);
}
void Pairs_get_target_from_base(void) {
ecs_world_t *world = ecs_mini();
ecs_entity_t rel = ecs_new_id(world);
ecs_entity_t tgt = ecs_new_id(world);
ecs_entity_t base = ecs_new_w_pair(world, rel, tgt);
ecs_entity_t inst = ecs_new_w_pair(world, EcsIsA, base);
test_assert(ecs_get_target(world, base, rel, 0) == tgt);
test_assert(ecs_get_target(world, inst, rel, 0) == tgt);
ecs_fini(world);
}
void Pairs_get_target_from_2nd_base(void) {
ecs_world_t *world = ecs_mini();
ecs_entity_t rel = ecs_new_id(world);
ecs_entity_t tgt = ecs_new_id(world);
ecs_entity_t base_1 = ecs_new_id(world);
ecs_entity_t base_2 = ecs_new_w_pair(world, rel, tgt);
ecs_entity_t inst = ecs_new_w_pair(world, EcsIsA, base_1);
ecs_add_pair(world, inst, EcsIsA, base_2);
test_assert(ecs_get_target(world, base_1, rel, 0) == 0);
test_assert(ecs_get_target(world, base_2, rel, 0) == tgt);
test_assert(ecs_get_target(world, inst, rel, 0) == tgt);
ecs_fini(world);
}
void Pairs_get_target_from_base_w_pair_on_instance(void) {
ecs_world_t *world = ecs_mini();
ecs_entity_t rel = ecs_new_id(world);
ecs_entity_t tgt_a = ecs_new_id(world);
ecs_entity_t tgt_b = ecs_new_id(world);
ecs_entity_t base = ecs_new_w_pair(world, rel, tgt_b);
ecs_entity_t inst = ecs_new_w_pair(world, EcsIsA, base);
ecs_add_pair(world, inst, rel, tgt_a);
test_assert(ecs_get_target(world, base, rel, 0) == tgt_b);
test_assert(ecs_get_target(world, inst, rel, 0) == tgt_a);
test_assert(ecs_get_target(world, inst, rel, 1) == tgt_b);
ecs_fini(world);
}
void Pairs_get_childof_target_from_base(void) {
ecs_world_t *world = ecs_mini();
ecs_entity_t parent = ecs_new_id(world);
ecs_entity_t base = ecs_new_w_pair(world, EcsChildOf, parent);
ecs_entity_t e = ecs_new_w_pair(world, EcsIsA, base);
test_assert(ecs_has_pair(world, base, EcsChildOf, parent));
test_assert(!ecs_has_pair(world, e, EcsChildOf, parent));
test_assert(ecs_get_target(world, e, EcsChildOf, 0) == 0);
test_assert(ecs_get_target(world, e, EcsChildOf, 1) == 0);
ecs_fini(world);
}
void Pairs_get_dontinherit_target_from_base(void) {
ecs_world_t *world = ecs_mini();
ECS_ENTITY(world, Rel, DontInherit);
ecs_entity_t parent = ecs_new_id(world);
ecs_entity_t base = ecs_new_w_pair(world, Rel, parent);
ecs_entity_t e = ecs_new_w_pair(world, EcsIsA, base);
test_assert(ecs_has_pair(world, base, Rel, parent));
test_assert(!ecs_has_pair(world, e, Rel, parent));
test_assert(ecs_get_target(world, e, Rel, 0) == 0);
test_assert(ecs_get_target(world, e, Rel, 1) == 0);
ecs_fini(world);
}
void Pairs_get_parent(void) {
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(ecs_get_target(world, e, EcsChildOf, 0) == parent);
test_assert(ecs_get_parent(world, e) == parent);
ecs_fini(world);
}
void Pairs_get_parent_from_root(void) {
ecs_world_t *world = ecs_mini();
ecs_entity_t e = ecs_new_id(world);
test_assert(ecs_get_parent(world, e) == 0);
ecs_fini(world);
}
void Pairs_get_target_for_id_from_self(void) {
ecs_world_t *world = ecs_mini();
ECS_TAG(world, Tag);
ecs_entity_t base = ecs_new(world, Tag);
ecs_entity_t e = ecs_new_w_pair(world, EcsIsA, base);
ecs_add_id(world, e, Tag);
ecs_entity_t result = ecs_get_target_for_id(world, e, EcsIsA, Tag);
test_assert(result != 0);
test_assert(result == e);
ecs_fini(world);
}
void Pairs_get_target_for_id_from_base(void) {
ecs_world_t *world = ecs_mini();
ECS_TAG(world, Tag);
ecs_entity_t base = ecs_new(world, Tag);
ecs_entity_t e = ecs_new_w_pair(world, EcsIsA, base);
ecs_entity_t result = ecs_get_target_for_id(world, e, EcsIsA, Tag);
test_assert(result != 0);
test_assert(result == base);
ecs_fini(world);
}
void Pairs_get_target_for_id_from_nested_base(void) {
ecs_world_t *world = ecs_mini();
ECS_TAG(world, Tag);
ecs_entity_t base = ecs_new(world, Tag);
ecs_entity_t base_2 = ecs_new_w_pair(world, EcsIsA, base);
ecs_entity_t e = ecs_new_w_pair(world, EcsIsA, base_2);
ecs_entity_t result = ecs_get_target_for_id(world, e, EcsIsA, Tag);
test_assert(result != 0);
test_assert(result == base);
ecs_fini(world);
}
void Pairs_get_target_for_id_not_found(void) {
ecs_world_t *world = ecs_mini();
ECS_TAG(world, Tag);
ecs_entity_t base = ecs_new_id(world);
ecs_entity_t base_2 = ecs_new_w_pair(world, EcsIsA, base);
ecs_entity_t e = ecs_new_w_pair(world, EcsIsA, base_2);
ecs_entity_t result = ecs_get_target_for_id(world, e, EcsIsA, Tag);
test_assert(result == 0);
ecs_fini(world);
}
void Pairs_get_target_for_wildcard_from_self(void) {
ecs_world_t *world = ecs_mini();
ECS_TAG(world, Rel);
ECS_TAG(world, Obj);
ecs_id_t pair = ecs_pair(Rel, Obj);
ecs_entity_t base = ecs_new_w_id(world, pair);
ecs_entity_t e = ecs_new_w_pair(world, EcsIsA, base);
ecs_add_id(world, e, pair);
ecs_entity_t result = ecs_get_target_for_id(world, e, EcsIsA,
ecs_pair(Rel, EcsWildcard));
test_assert(result != 0);
test_assert(result == e);
ecs_fini(world);
}
void Pairs_get_target_for_wildcard_from_base(void) {
ecs_world_t *world = ecs_mini();
ECS_TAG(world, Rel);
ECS_TAG(world, Obj);
ecs_id_t pair = ecs_pair(Rel, Obj);
ecs_entity_t base = ecs_new_w_id(world, pair);
ecs_entity_t e = ecs_new_w_pair(world, EcsIsA, base);
ecs_entity_t result = ecs_get_target_for_id(world, e, EcsIsA,
ecs_pair(Rel, EcsWildcard));
test_assert(result != 0);
test_assert(result == base);
ecs_fini(world);
}
void Pairs_get_target_for_wildcard_from_nested_base(void) {
ecs_world_t *world = ecs_mini();
ECS_TAG(world, Rel);
ECS_TAG(world, Obj);
ecs_id_t pair = ecs_pair(Rel, Obj);
ecs_entity_t base = ecs_new_w_id(world, pair);
ecs_entity_t base_2 = ecs_new_w_pair(world, EcsIsA, base);
ecs_entity_t e = ecs_new_w_pair(world, EcsIsA, base_2);
ecs_entity_t result = ecs_get_target_for_id(world, e, EcsIsA,
ecs_pair(Rel, EcsWildcard));
test_assert(result != 0);
test_assert(result == base);
ecs_fini(world);
}
void Pairs_ignore_childof_from_base(void) {
ecs_world_t *world = ecs_mini();
ECS_TAG(world, Rel);
ECS_TAG(world, Obj);
ecs_entity_t parent = ecs_new_id(world);
ecs_entity_t base = ecs_new_w_pair(world, EcsChildOf, parent);
ecs_entity_t e = ecs_new_w_pair(world, EcsIsA, base);
ecs_entity_t result = ecs_get_target_for_id(world, e, EcsIsA,
ecs_pair(EcsChildOf, parent));
test_assert(result == 0);
ecs_fini(world);
}
void Pairs_get_target_for_id_from_empty(void) {
ecs_world_t *world = ecs_mini();
ECS_TAG(world, Tag);
ecs_entity_t e = ecs_new_id(world);
ecs_entity_t result = ecs_get_target_for_id(world, e, EcsIsA, Tag);
test_assert(result == 0);
ecs_fini(world);
}
void Pairs_get_target_for_id_from_empty_no_rel(void) {
ecs_world_t *world = ecs_mini();
ECS_TAG(world, Tag);
ecs_entity_t e = ecs_new_id(world);
ecs_entity_t result = ecs_get_target_for_id(world, e, 0, Tag);
test_assert(result == 0);
ecs_fini(world);
}
void Pairs_get_target_for_id_not_empty_not_found(void) {
ecs_world_t *world = ecs_mini();
ECS_TAG(world, TagA);
ECS_TAG(world, TagB);
ecs_entity_t e = ecs_new(world, TagA);
ecs_entity_t result = ecs_get_target_for_id(world, e, 0, TagB);
test_assert(result == 0);
ecs_fini(world);
}
void Pairs_get_target_for_id_from_stage(void) {
ecs_world_t *world = ecs_mini();
ECS_TAG(world, Tag);
ecs_entity_t base = ecs_new(world, Tag);
ecs_entity_t e = ecs_new_w_pair(world, EcsIsA, base);
ecs_world_t *stage = ecs_get_stage(world, 0);
ecs_readonly_begin(world);
ecs_entity_t result = ecs_get_target_for_id(stage, e, EcsIsA, Tag);
test_assert(result != 0);
test_assert(result == base);
ecs_readonly_end(world);
ecs_fini(world);
}
void Pairs_get_target_for_id_no_id(void) {
ecs_world_t *world = ecs_mini();
ECS_TAG(world, Tag);
ecs_entity_t base = ecs_new(world, Tag);
ecs_entity_t e = ecs_new_w_pair(world, EcsIsA, base);
ecs_add_id(world, e, Tag);
ecs_entity_t result = ecs_get_target_for_id(world, e, EcsIsA, 0);
test_assert(result != 0);
test_assert(result == base);
ecs_fini(world);
}
void Pairs_add_exclusive_relation_twice(void) {
ecs_world_t *world = ecs_mini();
ECS_ENTITY(world, Rel, Exclusive);
ECS_TAG(world, ObjA);
ECS_TAG(world, ObjB);
ecs_entity_t e = ecs_new_id(world);
ecs_add_pair(world, e, Rel, ObjA);
test_assert( ecs_has_pair(world, e, Rel, ObjA));
ecs_add_pair(world, e, Rel, ObjB);
test_assert( ecs_has_pair(world, e, Rel, ObjB));
test_assert( !ecs_has_pair(world, e, Rel, ObjA));
ecs_fini(world);
}
void Pairs_add_same_exclusive_relation_twice(void) {
ecs_world_t *world = ecs_mini();
ECS_ENTITY(world, Rel, Exclusive);
ECS_TAG(world, ObjA);
ecs_entity_t e = ecs_new_id(world);
ecs_add_pair(world, e, Rel, ObjA);
test_assert( ecs_has_pair(world, e, Rel, ObjA));
ecs_add_pair(world, e, Rel, ObjA);
test_assert( ecs_has_pair(world, e, Rel, ObjA));
ecs_fini(world);
}
void Pairs_set_exclusive_relation_twice(void) {
ecs_world_t *world = ecs_mini();
ECS_COMPONENT(world, Position);
ECS_TAG(world, Start);
ECS_TAG(world, Stop);
ecs_add_id(world, ecs_id(Position), EcsExclusive);
ecs_entity_t e = ecs_new_id(world);
ecs_set_pair(world, e, Position, Start, {10, 20});
test_assert( ecs_has_pair(world, e, ecs_id(Position), Start));
ecs_set_pair(world, e, Position, Stop, {20, 30});
test_assert( ecs_has_pair(world, e, ecs_id(Position), Stop));
test_assert( !ecs_has_pair(world, e, ecs_id(Position), Start));
const Position *p = ecs_get_pair(world, e, Position, Stop);
test_assert(p != NULL);
test_int(p->x, 20);
test_int(p->y, 30);
p = ecs_get_pair(world, e, Position, Start);
test_assert(p == NULL);
ecs_fini(world);
}
void Pairs_add_exclusive_non_empty_table(void) {
ecs_world_t *world = ecs_mini();
ECS_TAG(world, TagA);
ECS_TAG(world, TagB);
ECS_TAG(world, TagC);
ECS_TAG(world, TagD);
ECS_ENTITY(world, Rel, Exclusive);
ECS_TAG(world, ObjA);
ECS_TAG(world, ObjB);
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(world, e, TagD);
ecs_add_pair(world, e, Rel, ObjA);
test_assert( ecs_has_pair(world, e, Rel, ObjA));
ecs_add_pair(world, e, Rel, ObjB);
test_assert( ecs_has_pair(world, e, Rel, ObjB));
test_assert( !ecs_has_pair(world, e, Rel, ObjA));
ecs_fini(world);
}
void Pairs_add_exclusive_non_empty_table_w_pairs(void) {
ecs_world_t *world = ecs_mini();
ECS_TAG(world, RelA);
ECS_ENTITY(world, Rel, Exclusive);
ECS_TAG(world, ObjA);
ECS_TAG(world, ObjB);
ECS_TAG(world, RelB);
ecs_entity_t e = ecs_new_id(world);
ecs_add_pair(world, e, RelA, ObjA);
ecs_add_pair(world, e, RelB, ObjA);
ecs_add_pair(world, e, Rel, ObjA);
test_assert( ecs_has_pair(world, e, Rel, ObjA));
ecs_add_pair(world, e, Rel, ObjB);
test_assert( ecs_has_pair(world, e, Rel, ObjB));
test_assert( !ecs_has_pair(world, e, Rel, ObjA));
ecs_fini(world);
}
void Pairs_add_pair_to_entity_w_exclusive_pair(void) {
ecs_world_t *world = ecs_mini();
ECS_TAG(world, ObjA);
ECS_TAG(world, RelA);
ECS_TAG(world, RelB);
ecs_entity_t e = ecs_new_id(world);
ecs_add_pair(world, e, EcsChildOf, ObjA);
test_assert( ecs_has_pair(world, e, EcsChildOf, ObjA));
ecs_add_pair(world, e, RelA, ObjA);
test_assert( ecs_has_pair(world, e, RelA, ObjA));
ecs_add_pair(world, e, RelB, ObjA);
test_assert( ecs_has_pair(world, e, RelB, ObjA));
ecs_fini(world);
}
void Pairs_add_pair_to_entity_w_scope(void) {
ecs_world_t *world = ecs_mini();
ECS_TAG(world, ObjA);
ECS_TAG(world, RelA);
ECS_TAG(world, RelB);
ecs_set_scope(world, ObjA);
ecs_entity_t e = ecs_new(world, 0);
ecs_add_pair(world, e, RelA, ObjA);
test_assert( ecs_has_pair(world, e, RelA, ObjA));
ecs_add_pair(world, e, RelB, ObjA);
test_assert( ecs_has_pair(world, e, RelB, ObjA));
ecs_set_scope(world, 0);
ecs_fini(world);
}
void Pairs_add_existing_exclusive_pair_after_pair(void) {
ecs_world_t *world = ecs_mini();
ECS_TAG(world, RelA);
ECS_TAG(world, RelB);
ECS_TAG(world, ObjA);
ecs_entity_t parent = ecs_new_id(world);
ecs_entity_t e = ecs_new_w_pair(world, EcsChildOf, parent);
ecs_add_pair(world, e, EcsChildOf, ObjA);
test_assert( ecs_has_pair(world, e, EcsChildOf, ObjA));
ecs_add_pair(world, e, RelA, ObjA);
test_assert( ecs_has_pair(world, e, EcsChildOf, ObjA));
test_assert( ecs_has_pair(world, e, RelA, ObjA));
ecs_add_pair(world, e, EcsChildOf, ObjA);
test_assert( ecs_has_pair(world, e, EcsChildOf, ObjA));
test_assert( ecs_has_pair(world, e, RelA, ObjA));
ecs_add_pair(world, e, RelB, ObjA);
test_assert( ecs_has_pair(world, e, EcsChildOf, ObjA));
test_assert( ecs_has_pair(world, e, RelA, ObjA));
test_assert( ecs_has_pair(world, e, RelB, ObjA));
ecs_fini(world);
}
void Pairs_add_remove_exclusive_property(void) {
ecs_world_t *world = ecs_mini();
ecs_entity_t rel = ecs_new_w_id(world, EcsExclusive);
ecs_remove_id(world, rel, EcsExclusive);
ecs_entity_t tgt_1 = ecs_new_id(world);
ecs_entity_t tgt_2 = ecs_new_id(world);
ecs_entity_t e = ecs_new_id(world);
ecs_add_pair(world, e, rel, tgt_1);
test_assert( ecs_has_pair(world, e, rel, tgt_1));
ecs_add_pair(world, e, rel, tgt_2);
test_assert( ecs_has_pair(world, e, rel, tgt_2));
test_assert( ecs_has_pair(world, e, rel, tgt_1));
ecs_fini(world);
}
void Pairs_add_symmetric_relation(void) {
ecs_world_t *world = ecs_mini();
ECS_TAG(world, Rel);
ECS_TAG(world, ObjA);
ECS_TAG(world, ObjB);
ecs_add_id(world, Rel, EcsSymmetric);
ecs_add_pair(world, ObjA, Rel, ObjB);
test_assert(ecs_has_pair(world, ObjA, Rel, ObjB));
test_assert(ecs_has_pair(world, ObjB, Rel, ObjA));
ecs_fini(world);
}
void Pairs_remove_symmetric_relation(void) {
ecs_world_t *world = ecs_mini();
ECS_TAG(world, Rel);
ECS_TAG(world, ObjA);
ECS_TAG(world, ObjB);
ecs_add_id(world, Rel, EcsSymmetric);
ecs_add_pair(world, ObjA, Rel, ObjB);
test_assert(ecs_has_pair(world, ObjA, Rel, ObjB));
test_assert(ecs_has_pair(world, ObjB, Rel, ObjA));
ecs_remove_pair(world, ObjA, Rel, ObjB);
test_assert(!ecs_has_pair(world, ObjA, Rel, ObjB));
test_assert(!ecs_has_pair(world, ObjB, Rel, ObjA));
ecs_fini(world);
}
void Pairs_delete_entity_w_symmetric_relation(void) {
ecs_world_t *world = ecs_mini();
ECS_TAG(world, Rel);
ECS_TAG(world, ObjA);
ECS_TAG(world, ObjB);
ecs_add_id(world, Rel, EcsSymmetric);
ecs_add_pair(world, ObjA, Rel, ObjB);
test_assert(ecs_has_pair(world, ObjA, Rel, ObjB));
test_assert(ecs_has_pair(world, ObjB, Rel, ObjA));
ecs_delete(world, ObjA);
test_assert(!ecs_has_pair(world, ObjB, Rel, ObjA));
ecs_fini(world);
}
void Pairs_add_symmetric_exclusive_relation(void) {
ecs_world_t *world = ecs_mini();
ECS_TAG(world, Rel);
ECS_TAG(world, ObjA);
ECS_TAG(world, ObjB);
ECS_TAG(world, ObjC);
ecs_add_id(world, Rel, EcsSymmetric);
ecs_add_id(world, Rel, EcsExclusive);
ecs_add_pair(world, ObjA, Rel, ObjB);
test_assert(ecs_has_pair(world, ObjA, Rel, ObjB));
test_assert(ecs_has_pair(world, ObjB, Rel, ObjA));
ecs_add_pair(world, ObjA, Rel, ObjC);
test_assert(ecs_has_pair(world, ObjA, Rel, ObjC));
test_assert(!ecs_has_pair(world, ObjB, Rel, ObjA));
test_assert(ecs_has_pair(world, ObjC, Rel, ObjA));
ecs_fini(world);
}
void Pairs_add_symmetric_recycled_relation(void) {
ecs_world_t *world = ecs_mini();
ecs_entity_t rel = ecs_new_id(world);
ecs_entity_t obj_a = ecs_new_id(world);
ecs_entity_t obj_b = ecs_new_id(world);
ecs_delete(world, rel);
rel = ecs_new_id(world);
ecs_delete(world, obj_a);
obj_a = ecs_new_id(world);
ecs_delete(world, obj_b);
obj_b = ecs_new_id(world);
test_assert(rel != (uint32_t)rel);
test_assert(obj_a != (uint32_t)obj_a);
test_assert(obj_b != (uint32_t)obj_b);
ecs_add_id(world, rel, EcsSymmetric);
ecs_add_pair(world, obj_a, rel, obj_b);
test_assert(ecs_has_pair(world, obj_a, rel, obj_b));
test_assert(ecs_has_pair(world, obj_b, rel, obj_a));
ecs_fini(world);
}
void Pairs_with(void) {
ecs_world_t *world = ecs_mini();
ECS_TAG(world, TagA);
ECS_ENTITY(world, TagB, (With, TagA));
ecs_entity_t e = ecs_new_id(world);
ecs_add(world, e, TagB);
test_assert( ecs_has(world, e, TagA));
test_assert( ecs_has(world, e, TagB));
ecs_fini(world);
}
void Pairs_2_with(void) {
ecs_world_t *world = ecs_mini();
ECS_TAG(world, TagA);
ECS_TAG(world, TagB);
ECS_ENTITY(world, TagC, (With, TagA), (With, TagB));
ecs_entity_t e = ecs_new_id(world);
ecs_add(world, e, TagC);
test_assert( ecs_has(world, e, TagA));
test_assert( ecs_has(world, e, TagB));
test_assert( ecs_has(world, e, TagC));
ecs_fini(world);
}
void Pairs_nested_with(void) {
ecs_world_t *world = ecs_mini();
ECS_TAG(world, TagA);
ECS_ENTITY(world, TagB, (With, TagA));
ECS_ENTITY(world, TagC, (With, TagB));
ecs_entity_t e = ecs_new_id(world);
ecs_add(world, e, TagC);
test_assert( ecs_has(world, e, TagA));
test_assert( ecs_has(world, e, TagB));
test_assert( ecs_has(world, e, TagC));
ecs_fini(world);
}
void Pairs_with_relation(void) {
ecs_world_t *world = ecs_mini();
ECS_TAG(world, Obj);
ECS_TAG(world, RelA);
ECS_ENTITY(world, RelB, (With, RelA));
ecs_entity_t e = ecs_new_w_pair(world, RelB, Obj);
test_assert( ecs_has_pair(world, e, RelA, Obj));
test_assert( ecs_has_pair(world, e, RelB, Obj));
ecs_fini(world);
}
void Pairs_2_with_relation(void) {
ecs_world_t *world = ecs_mini();
ECS_TAG(world, Obj);
ECS_TAG(world, RelA);
ECS_TAG(world, RelB);
ECS_ENTITY(world, RelC, (With, RelA), (With, RelB));
ecs_entity_t e = ecs_new_w_pair(world, RelC, Obj);
test_assert( ecs_has_pair(world, e, RelA, Obj));
test_assert( ecs_has_pair(world, e, RelB, Obj));
ecs_fini(world);
}
void Pairs_nested_with_relation(void) {
ecs_world_t *world = ecs_mini();
ECS_TAG(world, Obj);
ECS_TAG(world, RelA);
ECS_ENTITY(world, RelB, (With, RelA));
ECS_ENTITY(world, RelC, (With, RelB));
ecs_entity_t e = ecs_new_w_pair(world, RelC, Obj);
test_assert( ecs_has_pair(world, e, RelA, Obj));
test_assert( ecs_has_pair(world, e, RelB, Obj));
test_assert( ecs_has_pair(world, e, RelC, Obj));
ecs_fini(world);
}
void Pairs_with_for_existing(void) {
install_test_abort();
ecs_world_t *world = ecs_mini();
ECS_TAG(world, TagA);
ECS_TAG(world, TagB);
ecs_entity_t e = ecs_new_id(world);
ecs_add(world, e, TagB);
test_assert( !ecs_has(world, e, TagA));
test_assert( ecs_has(world, e, TagB));
test_expect_abort();
ecs_add_pair(world, TagB, EcsWith, TagA);
}
void Pairs_65k_relations(void) {
ecs_world_t *world = ecs_mini();
ecs_set_entity_range(world, 65536, 0);
ecs_entity_t rel = ecs_new_id(world);
ecs_entity_t obj = ecs_new_id(world);
ecs_entity_t e = ecs_new_w_pair(world, rel, obj);
test_assert(ecs_has_pair(world, e, rel, obj));
ecs_fini(world);
}
void Pairs_remove_wildcard(void) {
ecs_world_t *world = ecs_mini();
ECS_TAG(world, RelA);
ECS_TAG(world, RelB);
ECS_TAG(world, ObjA);
ECS_TAG(world, ObjB);
ecs_entity_t e = ecs_new_id(world);
ecs_add_pair(world, e, RelA, ObjA);
ecs_add_pair(world, e, RelA, ObjB);
ecs_add_pair(world, e, RelB, ObjA);
ecs_add_pair(world, e, RelB, ObjB);
test_assert( ecs_has_pair(world, e, RelA, ObjA));
test_assert( ecs_has_pair(world, e, RelA, ObjB));
test_assert( ecs_has_pair(world, e, RelB, ObjA));
test_assert( ecs_has_pair(world, e, RelB, ObjB));
ecs_remove_pair(world, e, RelA, EcsWildcard);
test_assert( !ecs_has_pair(world, e, RelA, ObjA));
test_assert( !ecs_has_pair(world, e, RelA, ObjB));
test_assert( ecs_has_pair(world, e, RelB, ObjA));
test_assert( ecs_has_pair(world, e, RelB, ObjB));
ecs_fini(world);
}
void Pairs_remove_relation_wildcard(void) {
ecs_world_t *world = ecs_mini();
ECS_TAG(world, RelA);
ECS_TAG(world, RelB);
ECS_TAG(world, ObjA);
ECS_TAG(world, ObjB);
ecs_entity_t e = ecs_new_id(world);
ecs_add_pair(world, e, RelA, ObjA);
ecs_add_pair(world, e, RelA, ObjB);
ecs_add_pair(world, e, RelB, ObjA);
ecs_add_pair(world, e, RelB, ObjB);
test_assert( ecs_has_pair(world, e, RelA, ObjA));
test_assert( ecs_has_pair(world, e, RelA, ObjB));
test_assert( ecs_has_pair(world, e, RelB, ObjA));
test_assert( ecs_has_pair(world, e, RelB, ObjB));
ecs_remove_pair(world, e, EcsWildcard, ObjA);
test_assert( !ecs_has_pair(world, e, RelA, ObjA));
test_assert( ecs_has_pair(world, e, RelA, ObjB));
test_assert( !ecs_has_pair(world, e, RelB, ObjA));
test_assert( ecs_has_pair(world, e, RelB, ObjB));
ecs_fini(world);
}
void Pairs_add_not_alive_relation(void) {
ecs_world_t *world = ecs_mini();
ecs_entity_t obj = ecs_new_id(world);
ecs_entity_t e = ecs_new_w_pair(world, 2000, obj);
test_assert(ecs_has_pair(world, e, 2000, obj));
ecs_fini(world);
}
void Pairs_remove_wildcard_all(void) {
ecs_world_t *world = ecs_mini();
ECS_TAG(world, RelA);
ECS_TAG(world, RelB);
ECS_TAG(world, ObjA);
ECS_TAG(world, ObjB);
ecs_entity_t e = ecs_new_id(world);
ecs_add_pair(world, e, RelA, ObjA);
ecs_add_pair(world, e, RelA, ObjB);
ecs_add_pair(world, e, RelB, ObjA);
ecs_add_pair(world, e, RelB, ObjB);
test_assert( ecs_has_pair(world, e, RelA, ObjA));
test_assert( ecs_has_pair(world, e, RelA, ObjB));
test_assert( ecs_has_pair(world, e, RelB, ObjA));
test_assert( ecs_has_pair(world, e, RelB, ObjB));
ecs_remove_pair(world, e, EcsWildcard, EcsWildcard);
test_assert( !ecs_has_pair(world, e, RelA, ObjA));
test_assert( !ecs_has_pair(world, e, RelA, ObjB));
test_assert( !ecs_has_pair(world, e, RelB, ObjA));
test_assert( !ecs_has_pair(world, e, RelB, ObjB));
ecs_fini(world);
}
void Pairs_inherit_exclusive(void) {
ecs_world_t *world = ecs_mini();
ECS_ENTITY(world, Rel, Exclusive);
ECS_TAG(world, ObjA);
ECS_TAG(world, ObjB);
ecs_entity_t base = ecs_new_w_pair(world, Rel, ObjA);
ecs_entity_t inst = ecs_new_w_pair(world, EcsIsA, base);
test_assert( ecs_has_pair(world, inst, Rel, ObjA));
ecs_add_pair(world, inst, Rel, ObjB);
test_assert( ecs_has_pair(world, inst, Rel, ObjB));
test_assert( !ecs_has_pair(world, inst, Rel, ObjA));
ecs_fini(world);
}
void Pairs_dont_inherit(void) {
ecs_world_t *world = ecs_mini();
ECS_TAG(world, TagA);
ecs_add_id(world, TagA, EcsDontInherit);
ECS_TAG(world, TagB);
ecs_entity_t base = ecs_new_w_id(world, TagA);
ecs_add(world, base, TagB);
ecs_entity_t inst = ecs_new_w_pair(world, EcsIsA, base);
test_assert( ecs_has(world, base, TagA));
test_assert( !ecs_has(world, inst, TagA));
test_assert( ecs_has(world, base, TagB));
test_assert( ecs_has(world, inst, TagB));
ecs_fini(world);
}
void Pairs_has_wildcard_w_pair(void) {
ecs_world_t *world = ecs_mini();
ECS_TAG(world, Rel);
ECS_TAG(world, Obj);
ecs_entity_t e = ecs_new_w_pair(world, Rel, Obj);
test_bool(ecs_has_pair(world, e, EcsWildcard, EcsWildcard), true);
test_bool(ecs_has_pair(world, e, Rel, EcsWildcard), true);
test_bool(ecs_has_pair(world, e, EcsWildcard, Obj), true);
test_bool(ecs_has_pair(world, e, Rel, Obj), true);
test_bool(ecs_has_id(world, e, EcsWildcard), false);
ecs_fini(world);
}
void Pairs_has_pair_wildcard_w_tag(void) {
ecs_world_t *world = ecs_mini();
ECS_TAG(world, Tag);
ecs_entity_t e = ecs_new(world, Tag);
test_bool(ecs_has_pair(world, e, EcsWildcard, EcsWildcard), false);
test_bool(ecs_has_id(world, e, Tag), true);
test_bool(ecs_has_id(world, e, EcsWildcard), true);
ecs_fini(world);
}
void Pairs_oneof_self(void) {
ecs_world_t *world = ecs_mini();
ECS_ENTITY(world, Rel, OneOf);
ECS_ENTITY(world, ObjA, (ChildOf, Rel));
ECS_ENTITY(world, ObjB, (ChildOf, Rel));
ecs_entity_t e = ecs_new_id(world);
ecs_add_pair(world, e, Rel, ObjA);
test_assert(ecs_has_pair(world, e, Rel, ObjA));
ecs_add_pair(world, e, Rel, ObjB);
test_assert(ecs_has_pair(world, e, Rel, ObjB));
ecs_fini(world);
}
void Pairs_oneof_other(void) {
ecs_world_t *world = ecs_mini();
ECS_TAG(world, Parent);
ECS_ENTITY(world, Rel, (OneOf, Parent));
ECS_ENTITY(world, ObjA, (ChildOf, Parent));
ECS_ENTITY(world, ObjB, (ChildOf, Parent));
ecs_entity_t e = ecs_new_id(world);
ecs_add_pair(world, e, Rel, ObjA);
test_assert(ecs_has_pair(world, e, Rel, ObjA));
ecs_add_pair(world, e, Rel, ObjB);
test_assert(ecs_has_pair(world, e, Rel, ObjB));
ecs_fini(world);
}
void Pairs_oneof_self_constraint_violated(void) {
install_test_abort();
ecs_world_t *world = ecs_mini();
ECS_ENTITY(world, Rel, OneOf);
ECS_ENTITY(world, ObjA, (ChildOf, Rel));
ECS_ENTITY(world, ObjB, (ChildOf, Rel));
ECS_TAG(world, ObjC);
ecs_entity_t e = ecs_new_id(world);
test_expect_abort();
ecs_add_pair(world, e, Rel, ObjC);
}
void Pairs_oneof_other_constraint_violated(void) {
install_test_abort();
ecs_world_t *world = ecs_mini();
ECS_TAG(world, Parent);
ECS_ENTITY(world, Rel, (OneOf, Parent));
ECS_ENTITY(world, ObjA, (ChildOf, Parent));
ECS_ENTITY(world, ObjB, (ChildOf, Parent));
ECS_TAG(world, ObjC);
ecs_entity_t e = ecs_new_id(world);
test_expect_abort();
ecs_add_pair(world, e, Rel, ObjC);
}
void Pairs_oneof_other_rel_parent_constraint_violated(void) {
install_test_abort();
ecs_world_t *world = ecs_mini();
ECS_TAG(world, Parent);
ECS_ENTITY(world, Rel, (OneOf, Parent));
ECS_ENTITY(world, ObjA, (ChildOf, Parent));
ECS_ENTITY(world, ObjB, (ChildOf, Parent));
ECS_ENTITY(world, ObjC, (ChildOf, Rel));
ecs_entity_t e = ecs_new_id(world);
test_expect_abort();
ecs_add_pair(world, e, Rel, ObjC);
}