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

730 lines
18 KiB
C

#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);
}