quakeforge/libs/ecs/test/test-registry.c
Bill Currie 35eec0b2e5 [ecs] Implement hierarchies as components
The main goal of this change was to make it easier to tell when a
hierarchy has been deleted, but as a side benefit, it got rid of the use
of PR_RESMAP. Also, it's easy to track the number of hierarchies.

Unfortunately, it showed how brittle the component side of the ECS is
(scene and canvas registries assumed their components were the first (no
long the case), thus the sweeping changes).

Centerprint doesn't work (but it hasn't for a while).
2024-01-02 16:38:01 +09:00

154 lines
3.8 KiB
C

#ifdef HAVE_CONFIG_H
# include "config.h"
#endif
#include <stdio.h>
#include <string.h>
#include <unistd.h>
#include "QF/ecs.h"
static int
test_new_del (void)
{
ecs_registry_t *reg = ECS_NewRegistry ("new del");
ECS_CreateComponentPools (reg);
if (!reg) {
printf ("could not create registry\n");
return 0;
}
if (reg->max_entities && !reg->entities) {
printf ("Non-zero max_entities with null entities pointer\n");
return 0;
}
if (!reg->max_entities && reg->entities) {
printf ("Zero max_entities with non-null entities pointer\n");
return 0;
}
if (reg->num_entities > reg->max_entities) {
printf ("num_entities > max_entities\n");
return 0;
}
if (reg->num_entities) {
printf ("Fresh registry has entities\n");
return 0;
}
if (reg->available) {
printf ("Fresh registry has recycled entities\n");
return 0;
}
ECS_DelRegistry (reg);
return 1;
}
#define NUM_ENTS 5
static int
test_entities (void)
{
ecs_registry_t *reg = ECS_NewRegistry ("entities");
ECS_CreateComponentPools (reg);
uint32_t entities[NUM_ENTS];
for (int i = 0; i < NUM_ENTS; i++) {
entities[i] = ECS_NewEntity (reg);
}
if (!reg->max_entities || !reg->entities) {
printf ("Zero max_entities or non-null entities pointer\n");
return 0;
}
if (reg->available) {
printf ("unexpected recycled entities\n");
return 0;
}
if (reg->num_entities != NUM_ENTS) {
printf ("wrong number of entities in registry: %d vs %d\n", NUM_ENTS,
reg->num_entities);
return 0;
}
for (int i = 0; i < NUM_ENTS; i++) {
if (Ent_Index (entities[i]) > reg->num_entities) {
printf ("bad entity returned: %d > %d\n", Ent_Index (entities[i]),
reg->num_entities);
return 0;
}
if (Ent_Generation (entities[i])) {
printf ("fresh entity not generation 0\n");
return 0;
}
for (int j = 0; j < i; j++) {
if (Ent_Index (entities[j]) == Ent_Index (entities[i])) {
printf ("duplicate entity id\n");
return 0;
}
}
if (reg->entities[Ent_Index (entities[i])] != entities[i]) {
printf ("wrong entity in entities array: %d %d\n",
entities[i], reg->entities[Ent_Index (entities[i])]);
return 0;
}
}
ECS_DelEntity (reg, entities[2]);
ECS_DelEntity (reg, entities[0]);
if (reg->entities[Ent_Index (entities[2])] == entities[2]) {
printf ("deleted entity not deleted: %d %d\n",
entities[2], reg->entities[Ent_Index (entities[2])]);
return 0;
}
if (reg->entities[Ent_Index (entities[0])] == entities[0]) {
printf ("deleted entity not deleted: %d %d\n",
entities[0], reg->entities[Ent_Index (entities[0])]);
return 0;
}
if (reg->available != 2) {
printf ("not 2 available entity for recycling\n");
return 0;
}
for (uint32_t i = reg->next, c = 0; i != Ent_Index (nullent);
i = Ent_Index (reg->entities[i]), c++) {
if (c >= reg->available || i >= reg->num_entities) {
printf ("invalid deleted entity chain\n");
return 0;
}
if (Ent_Index (reg->entities[i]) == i) {
printf ("deleted entity points to itself\n");
return 0;
}
//printf ("%x\n", reg->entities[i]);
}
entities[2] = ECS_NewEntity (reg);
if (reg->available != 1) {
printf ("not 1 available entity for recycling\n");
return 0;
}
entities[0] = ECS_NewEntity (reg);
if (reg->available != 0) {
printf ("not 0 available entities for recycling\n");
return 0;
}
if (reg->num_entities != NUM_ENTS) {
printf ("wrong number of entities in registry: %d vs %d\n", NUM_ENTS,
reg->num_entities);
return 0;
}
if (!Ent_Generation (entities[2]) || !Ent_Generation (entities[0])) {
printf ("recycled entity generations not updated\n");
return 0;
}
//for (int i = 0; i < NUM_ENTS; i++) {
// printf ("%x\n", entities[i]);
//}
ECS_DelRegistry (reg);
return 1;
}
int
main (void)
{
if (!test_new_del ()) { return 1; }
if (!test_entities ()) { return 1; }
return 0;
}