Repair embedded dependency build and test setup

Isolate vendored test registration, namespace project error codes, and update dependency revisions. Fix mutable sprite path handling, out-of-tree fixtures, and charviewer initialization while documenting the outstanding character-to-sprite refcount bug.

Co-authored-by: Codex (GPT-5) <noreply@openai.com>
This commit is contained in:
2026-07-29 18:01:05 -04:00
parent 74867ea82e
commit cf9ebb206f
22 changed files with 209 additions and 64 deletions

View File

@@ -2,6 +2,7 @@
handle_unhandled_error(errctx);
#include <akerror.h>
#include <akgl/error.h>
#define UNHANDLED_ERROR_EXIT 0
#define UNHANDLED_ERROR_SET 1
@@ -42,7 +43,7 @@ akerr_ErrorContext *akgl_actor_update_noop(akgl_Actor *obj)
// Currently the renderer assumes there is a global variable named `renderer`
int akgl_actor_rendered;
akerr_ErrorContext *akgl_actor_render_noop(akgl_Actor *obj, SDL_Renderer *r)
akerr_ErrorContext *akgl_actor_render_noop(akgl_Actor *obj)
{
PREPARE_ERROR(errctx);
akgl_actor_rendered = 1;
@@ -129,13 +130,13 @@ akerr_ErrorContext *test_registry_actor_iterator_updaterender(void)
FAIL_ZERO_BREAK(
unhandled_error_context,
akgl_actor_updated,
AKERR_BEHAVIOR,
AKGL_ERR_BEHAVIOR,
"actor->updatefunc not called by the iterator"
);
FAIL_ZERO_BREAK(
unhandled_error_context,
akgl_actor_rendered,
AKERR_BEHAVIOR,
AKGL_ERR_BEHAVIOR,
"actor->renderfunc not called by the iterator"
);
} CLEANUP {
@@ -235,7 +236,7 @@ akerr_ErrorContext *test_actor_manage_children(void)
CATCH(errctx, parent->addchild(parent, child));
} CLEANUP {
if ( errctx == NULL ) {
FAIL(errctx, AKERR_BEHAVIOR, "addchild does not throw AKERR_RELATIONSHIP when child already has a parent");
FAIL(errctx, AKGL_ERR_BEHAVIOR, "addchild does not throw AKERR_RELATIONSHIP when child already has a parent");
}
} PROCESS(errctx) {
} HANDLE(errctx, AKERR_RELATIONSHIP) {
@@ -248,7 +249,7 @@ akerr_ErrorContext *test_actor_manage_children(void)
CATCH(errctx, parent->addchild(parent, child));
} CLEANUP {
if ( errctx == NULL ) {
FAIL(errctx, AKERR_BEHAVIOR, "addchild does not throw AKERR_OUTOFBOUNDS when all children already set");
FAIL(errctx, AKGL_ERR_BEHAVIOR, "addchild does not throw AKERR_OUTOFBOUNDS when all children already set");
}
} PROCESS(errctx) {
} HANDLE(errctx, AKERR_OUTOFBOUNDS) {

View File

@@ -1,7 +1,8 @@
{
"name": "testcharacter",
"velocity_x": 0.20,
"velocity_y": 0.20,
"movementspeed": 1,
"acceleration_x": 0.20,
"acceleration_y": 0.20,
"sprite_mappings": [
{
"state": [
@@ -12,7 +13,7 @@
},
{
"state": [
"ACTOR_STATE_DEAD"
"AKGL_ACTOR_STATE_DEAD"
],
"sprite": "testsprite2"
}

View File

@@ -1,6 +1,6 @@
{
"spritesheet": {
"filename": "assets/spritesheet.png",
"filename": "spritesheet.png",
"frame_width": 48,
"frame_height": 48
},

View File

@@ -1,6 +1,6 @@
{
"spritesheet": {
"filename": "assets/spritesheet.png",
"filename": "spritesheet.png",
"frame_width": 48,
"frame_height": 48
},

View File

@@ -50,6 +50,7 @@ akerr_ErrorContext *test_character_sprite_mgmt()
PREPARE_ERROR(errctx);
ATTEMPT {
CATCH(errctx, akgl_heap_next_character(&testchar));
CATCH(errctx, akgl_character_initialize(testchar, "testchar"));
CATCH(errctx, akgl_sprite_load_json("assets/testsprite.json"));
testsprite = SDL_GetPointerProperty(AKGL_REGISTRY_SPRITE, "testsprite", NULL);
FAIL_ZERO_BREAK(
@@ -89,6 +90,7 @@ akerr_ErrorContext *test_character_iterate_state_sprites()
PREPARE_ERROR(errctx);
ATTEMPT {
CATCH(errctx, akgl_heap_next_character(&testchar));
CATCH(errctx, akgl_character_initialize(testchar, "testchar"));
CATCH(errctx, akgl_sprite_load_json("assets/testsprite.json"));
testsprite = SDL_GetPointerProperty(AKGL_REGISTRY_SPRITE, "testsprite", NULL);
FAIL_ZERO_BREAK(
@@ -169,8 +171,8 @@ akerr_ErrorContext *test_akgl_character_load_json()
CATCH(errctx, testcharacter->sprite_get(testcharacter, AKGL_ACTOR_STATE_DEAD, &comparesprite));
FAIL_ZERO_BREAK(errctx, (comparesprite == testsprite2), AKERR_VALUE, "Wrong sprite for state AKGL_ACTOR_STATE_DEAD");
FAIL_ZERO_BREAK(errctx, (testcharacter->vx != 0.200000003), AKERR_VALUE, "Wrong X velocity for test character");
FAIL_ZERO_BREAK(errctx, (testcharacter->vy != 0.200000003), AKERR_VALUE, "Wrong Y velocity for test character");
FAIL_ZERO_BREAK(errctx, (testcharacter->ax != 0.200000003), AKERR_VALUE, "Wrong X acceleration for test character");
FAIL_ZERO_BREAK(errctx, (testcharacter->ay != 0.200000003), AKERR_VALUE, "Wrong Y acceleration for test character");
// Release our handles on the sprites so the character's heap_release can reduce them to 0
CATCH(errctx, akgl_heap_release_sprite(testsprite));

View File

@@ -68,7 +68,7 @@ int main(void)
AKGL_REGISTRY_CHARACTER,
"little guy",
NULL);
FAIL_ZERO_BREAK(errctx, actorptr->basechar, AKERR_REGISTRY, "Can't load character 'little guy' from the registry");
FAIL_ZERO_BREAK(errctx, actorptr->basechar, AKGL_ERR_REGISTRY, "Can't load character 'little guy' from the registry");
actorptr->movement_controls_face = false;
actorptr->state = (AKGL_ACTOR_STATE_ALIVE | AKGL_ACTOR_STATE_FACE_LEFT);
actorptr->x = 320;

View File

@@ -43,7 +43,7 @@ akerr_ErrorContext *test_akgl_registry_init(RegistryFuncPtr funcptr)
} PROCESS(errctx) {
} FINISH(errctx, true);
FAIL_RETURN(errctx, AKERR_BEHAVIOR, "SDL memory allocator fails but registry reports successful property creation");
FAIL_RETURN(errctx, AKGL_ERR_BEHAVIOR, "SDL memory allocator fails but registry reports successful property creation");
}
akerr_ErrorContext *test_akgl_registry_init_creation_failures(void)

View File

@@ -1,5 +1,6 @@
#include <string.h>
#include <akerror.h>
#include <akgl/error.h>
#include <akgl/heap.h>
#include <akgl/staticstring.h>
@@ -111,7 +112,7 @@ akerr_ErrorContext *test_akgl_string_initialize(void)
FAIL_NONZERO_BREAK(errctx, strcmp((char *)&ptr->data, "Test value"), AKERR_VALUE, "Expected 'Test value', got %s", (char *)&ptr->data);
CATCH(errctx, akgl_heap_release_string(NULL));
FAIL_BREAK(errctx, AKERR_BEHAVIOR, "Failure to properly handle NULL pointer");
FAIL_BREAK(errctx, AKGL_ERR_BEHAVIOR, "Failure to properly handle NULL pointer");
} CLEANUP {
} PROCESS(errctx) {
} FINISH(errctx, true);

View File

@@ -26,7 +26,7 @@ akerr_ErrorContext *test_tilemap_akgl_get_json_tilemap_property(void)
AKGL_MAX_STRING_LENGTH,
"%s%s",
SDL_GetBasePath(),
"assets/snippets/test_tilemap_akgl_get_json_tilemap_property.json"
"assets/snippets/test_tilemap_get_json_tilemap_property.json"
);
jsondoc = json_load_file((char *)&tmpstr->data, 0, (json_error_t *)&jsonerr);
FAIL_ZERO_BREAK(errctx, jsondoc, AKERR_NULLPOINTER, "Failure loading json fixture: %s", (char *)jsonerr.text);

View File

@@ -1,5 +1,6 @@
#include <SDL3/SDL.h>
#include <akerror.h>
#include <akgl/error.h>
#include <akgl/util.h>
akerr_ErrorContext *test_akgl_rectangle_points_nullpointers(void)
@@ -10,7 +11,7 @@ akerr_ErrorContext *test_akgl_rectangle_points_nullpointers(void)
ATTEMPT {
CATCH(errctx, akgl_rectangle_points(NULL, NULL));
FAIL_BREAK(errctx, AKERR_BEHAVIOR, "akgl_rectangle_points fails to FAIL with all NULL pointers");
FAIL_BREAK(errctx, AKGL_ERR_BEHAVIOR, "akgl_rectangle_points fails to FAIL with all NULL pointers");
} CLEANUP {
} PROCESS(errctx) {
} HANDLE(errctx, AKERR_NULLPOINTER) {
@@ -19,7 +20,7 @@ akerr_ErrorContext *test_akgl_rectangle_points_nullpointers(void)
ATTEMPT {
CATCH(errctx, akgl_rectangle_points(NULL, &testrect));
FAIL_BREAK(errctx, AKERR_BEHAVIOR, "akgl_rectangle_points fails to FAIL with NULL SDL_FRect pointer");
FAIL_BREAK(errctx, AKGL_ERR_BEHAVIOR, "akgl_rectangle_points fails to FAIL with NULL SDL_FRect pointer");
} CLEANUP {
} PROCESS(errctx) {
} HANDLE(errctx, AKERR_NULLPOINTER) {
@@ -28,7 +29,7 @@ akerr_ErrorContext *test_akgl_rectangle_points_nullpointers(void)
ATTEMPT {
CATCH(errctx, akgl_rectangle_points(&points, NULL));
FAIL_BREAK(errctx, AKERR_BEHAVIOR, "akgl_rectangle_points fails to FAIL with NULL RectanglePoints pointer");
FAIL_BREAK(errctx, AKGL_ERR_BEHAVIOR, "akgl_rectangle_points fails to FAIL with NULL RectanglePoints pointer");
} CLEANUP {
} PROCESS(errctx) {
} HANDLE(errctx, AKERR_NULLPOINTER) {
@@ -63,7 +64,7 @@ akerr_ErrorContext *test_akgl_rectangle_points_math(void)
points.bottomright.y != 32 ) {
FAIL_BREAK(
errctx,
AKERR_BEHAVIOR,
AKGL_ERR_BEHAVIOR,
"akgl_rectangle_points incorrectly calculated points for {x=0, y=0, w=32, h=32} to {topleft={%d, %d}, topright={%d, %d}, bottomleft={%d, %d}, bottomright={%d, %d}}",
points.topleft.x, points.topleft.y,
points.topright.x, points.topright.y,
@@ -87,7 +88,7 @@ akerr_ErrorContext *test_akgl_collide_point_rectangle_nullpointers(void)
ATTEMPT {
CATCH(errctx, akgl_collide_point_rectangle(&testpoint, &testrectpoints, NULL));
FAIL_BREAK(errctx, AKERR_BEHAVIOR, "akgl_collide_point_rectangle(*, *, NULL) failed");
FAIL_BREAK(errctx, AKGL_ERR_BEHAVIOR, "akgl_collide_point_rectangle(*, *, NULL) failed");
} CLEANUP {
} PROCESS(errctx) {
} HANDLE(errctx, AKERR_NULLPOINTER) {
@@ -96,7 +97,7 @@ akerr_ErrorContext *test_akgl_collide_point_rectangle_nullpointers(void)
ATTEMPT {
CATCH(errctx, akgl_collide_point_rectangle(&testpoint, NULL, &testcollide));
FAIL_BREAK(errctx, AKERR_BEHAVIOR, "akgl_collide_point_rectangle(*, NULL, *) failed");
FAIL_BREAK(errctx, AKGL_ERR_BEHAVIOR, "akgl_collide_point_rectangle(*, NULL, *) failed");
} CLEANUP {
} PROCESS(errctx) {
} HANDLE(errctx, AKERR_NULLPOINTER) {
@@ -105,7 +106,7 @@ akerr_ErrorContext *test_akgl_collide_point_rectangle_nullpointers(void)
ATTEMPT {
CATCH(errctx, akgl_collide_point_rectangle(NULL, &testrectpoints, &testcollide));
FAIL_BREAK(errctx, AKERR_BEHAVIOR, "akgl_collide_point_rectangle(NULL, *, *) failed");
FAIL_BREAK(errctx, AKGL_ERR_BEHAVIOR, "akgl_collide_point_rectangle(NULL, *, *) failed");
} CLEANUP {
} PROCESS(errctx) {
} HANDLE(errctx, AKERR_NULLPOINTER) {
@@ -114,7 +115,7 @@ akerr_ErrorContext *test_akgl_collide_point_rectangle_nullpointers(void)
ATTEMPT {
CATCH(errctx, akgl_collide_point_rectangle(NULL, NULL, NULL));
FAIL_BREAK(errctx, AKERR_BEHAVIOR, "akgl_collide_point_rectangle(NULL, NULL, NULL) failed");
FAIL_BREAK(errctx, AKGL_ERR_BEHAVIOR, "akgl_collide_point_rectangle(NULL, NULL, NULL) failed");
} CLEANUP {
} PROCESS(errctx) {
} HANDLE(errctx, AKERR_NULLPOINTER) {
@@ -142,14 +143,14 @@ akerr_ErrorContext *test_akgl_collide_point_rectangle_logic(void)
CATCH(errctx, akgl_rectangle_points(&testrectpoints, &testrect));
CATCH(errctx, akgl_collide_point_rectangle(&testpoint, &testrectpoints, &testcollide));
if ( testcollide == false ) {
FAIL_BREAK(errctx, AKERR_BEHAVIOR, "Valid collision missed");
FAIL_BREAK(errctx, AKGL_ERR_BEHAVIOR, "Valid collision missed");
}
testpoint.x = 48;
testpoint.y = 48;
CATCH(errctx, akgl_collide_point_rectangle(&testpoint, &testrectpoints, &testcollide));
if ( testcollide == true ) {
FAIL_BREAK(errctx, AKERR_BEHAVIOR, "Invalid collision reported");
FAIL_BREAK(errctx, AKGL_ERR_BEHAVIOR, "Invalid collision reported");
}
} CLEANUP {
} PROCESS(errctx) {
@@ -167,7 +168,7 @@ akerr_ErrorContext *test_akgl_collide_rectangles_nullpointers(void)
ATTEMPT {
CATCH(errctx, akgl_collide_rectangles(&testrect1, &testrect2, NULL));
FAIL_BREAK(errctx, AKERR_BEHAVIOR, "akgl_collide_rectangles(*, *, NULL) failed");
FAIL_BREAK(errctx, AKGL_ERR_BEHAVIOR, "akgl_collide_rectangles(*, *, NULL) failed");
} CLEANUP {
} PROCESS(errctx) {
} HANDLE(errctx, AKERR_NULLPOINTER) {
@@ -176,7 +177,7 @@ akerr_ErrorContext *test_akgl_collide_rectangles_nullpointers(void)
ATTEMPT {
CATCH(errctx, akgl_collide_rectangles(&testrect1, NULL, &testcollide));
FAIL_BREAK(errctx, AKERR_BEHAVIOR, "akgl_collide_rectangles(*, NULL, *) failed");
FAIL_BREAK(errctx, AKGL_ERR_BEHAVIOR, "akgl_collide_rectangles(*, NULL, *) failed");
} CLEANUP {
} PROCESS(errctx) {
} HANDLE(errctx, AKERR_NULLPOINTER) {
@@ -185,7 +186,7 @@ akerr_ErrorContext *test_akgl_collide_rectangles_nullpointers(void)
ATTEMPT {
CATCH(errctx, akgl_collide_rectangles(NULL, &testrect2, &testcollide));
FAIL_BREAK(errctx, AKERR_BEHAVIOR, "akgl_collide_rectangles(NULL, *, *) failed");
FAIL_BREAK(errctx, AKGL_ERR_BEHAVIOR, "akgl_collide_rectangles(NULL, *, *) failed");
} CLEANUP {
} PROCESS(errctx) {
} HANDLE(errctx, AKERR_NULLPOINTER) {
@@ -194,7 +195,7 @@ akerr_ErrorContext *test_akgl_collide_rectangles_nullpointers(void)
ATTEMPT {
CATCH(errctx, akgl_collide_rectangles(NULL, NULL, NULL));
FAIL_BREAK(errctx, AKERR_BEHAVIOR, "akgl_collide_rectangles(NULL, NULL, NULL) failed");
FAIL_BREAK(errctx, AKGL_ERR_BEHAVIOR, "akgl_collide_rectangles(NULL, NULL, NULL) failed");
} CLEANUP {
} PROCESS(errctx) {
} HANDLE(errctx, AKERR_NULLPOINTER) {
@@ -222,14 +223,14 @@ akerr_ErrorContext *test_akgl_collide_rectangles_logic(void)
// Collision overlapping on the top left
CATCH(errctx, akgl_collide_rectangles(&testrect1, &testrect2, &testcollide));
if ( testcollide == false ) {
FAIL_BREAK(errctx, AKERR_BEHAVIOR, "Valid collision missed");
FAIL_BREAK(errctx, AKGL_ERR_BEHAVIOR, "Valid collision missed");
}
// Collision overlapping on the top right
testrect1.x = 64;
CATCH(errctx, akgl_collide_rectangles(&testrect1, &testrect2, &testcollide));
if ( testcollide == false ) {
FAIL_BREAK(errctx, AKERR_BEHAVIOR, "Valid collision missed");
FAIL_BREAK(errctx, AKGL_ERR_BEHAVIOR, "Valid collision missed");
}
// Collision overlapping on the bottom left
@@ -237,7 +238,7 @@ akerr_ErrorContext *test_akgl_collide_rectangles_logic(void)
testrect1.y = 32;
CATCH(errctx, akgl_collide_rectangles(&testrect1, &testrect2, &testcollide));
if ( testcollide == false ) {
FAIL_BREAK(errctx, AKERR_BEHAVIOR, "Valid collision missed");
FAIL_BREAK(errctx, AKGL_ERR_BEHAVIOR, "Valid collision missed");
}
// Collision overlapping on the bottom right
@@ -245,7 +246,7 @@ akerr_ErrorContext *test_akgl_collide_rectangles_logic(void)
testrect1.y = 32;
CATCH(errctx, akgl_collide_rectangles(&testrect1, &testrect2, &testcollide));
if ( testcollide == false ) {
FAIL_BREAK(errctx, AKERR_BEHAVIOR, "Valid collision missed");
FAIL_BREAK(errctx, AKGL_ERR_BEHAVIOR, "Valid collision missed");
}
// Collision overlapping the top edge
@@ -255,7 +256,7 @@ akerr_ErrorContext *test_akgl_collide_rectangles_logic(void)
testrect1.h = 32;
CATCH(errctx, akgl_collide_rectangles(&testrect1, &testrect2, &testcollide));
if ( testcollide == false ) {
FAIL_BREAK(errctx, AKERR_BEHAVIOR, "Valid collision missed");
FAIL_BREAK(errctx, AKGL_ERR_BEHAVIOR, "Valid collision missed");
}
// Collision overlapping the left edge
@@ -265,7 +266,7 @@ akerr_ErrorContext *test_akgl_collide_rectangles_logic(void)
testrect1.h = 80;
CATCH(errctx, akgl_collide_rectangles(&testrect1, &testrect2, &testcollide));
if ( testcollide == false ) {
FAIL_BREAK(errctx, AKERR_BEHAVIOR, "Valid collision missed");
FAIL_BREAK(errctx, AKGL_ERR_BEHAVIOR, "Valid collision missed");
}
// Collision overlapping the right edge
@@ -275,7 +276,7 @@ akerr_ErrorContext *test_akgl_collide_rectangles_logic(void)
testrect1.h = 80;
CATCH(errctx, akgl_collide_rectangles(&testrect1, &testrect2, &testcollide));
if ( testcollide == false ) {
FAIL_BREAK(errctx, AKERR_BEHAVIOR, "Valid collision missed");
FAIL_BREAK(errctx, AKGL_ERR_BEHAVIOR, "Valid collision missed");
}
// Collision overlapping the bottom edge
@@ -285,7 +286,7 @@ akerr_ErrorContext *test_akgl_collide_rectangles_logic(void)
testrect1.h = 32;
CATCH(errctx, akgl_collide_rectangles(&testrect1, &testrect2, &testcollide));
if ( testcollide == false ) {
FAIL_BREAK(errctx, AKERR_BEHAVIOR, "Valid collision missed");
FAIL_BREAK(errctx, AKGL_ERR_BEHAVIOR, "Valid collision missed");
}
// Not colliding
@@ -295,7 +296,7 @@ akerr_ErrorContext *test_akgl_collide_rectangles_logic(void)
testrect1.h = 16;
CATCH(errctx, akgl_collide_rectangles(&testrect1, &testrect2, &testcollide));
if ( testcollide == true ) {
FAIL_BREAK(errctx, AKERR_BEHAVIOR, "Invalid collision reported");
FAIL_BREAK(errctx, AKGL_ERR_BEHAVIOR, "Invalid collision reported");
}
} CLEANUP {