Remove the corner helpers akgl_collide_rectangles no longer uses
akgl_rectangle_points, akgl_collide_point_rectangle, akgl_Point and akgl_RectanglePoints go. They were the intermediate form of an implementation that changed: akgl_collide_rectangles was eight corner-containment tests built on them, and it has been four span comparisons since the cross-case fix. Nothing outside tests/ called either function, and a point-in-rectangle test is four comparisons a caller can write without a struct conversion in front of them. akgl_collide_rectangles stays. It has two correct callers in the sidescroller asking a game-level overlap question -- a coin, a hazard, from an updatefunc -- where a bool is the whole answer and a proxy plus a narrowphase call would be computing a normal nothing reads. TODO.md records the split rather than leaving it to be rediscovered. Public API removal, so 194 exported akgl_ symbols against 196, and the manual's counts move with them. The perf suite loses its rectangle_points row; the all-pairs sweep stays as the control it is now labelled, and PERFORMANCE.md says what 0.8.0 measured against it -- 188.5 us for 32,640 pairs at 256 actors, where a whole step with collision attached is 54.1 us doing strictly more. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01KzBDV2fqgnUAcqCKqKvc71
This commit is contained in:
187
tests/util.c
187
tests/util.c
@@ -28,172 +28,6 @@ static int live_error_contexts(void)
|
||||
return live;
|
||||
}
|
||||
|
||||
akerr_ErrorContext *test_akgl_rectangle_points_nullpointers(void)
|
||||
{
|
||||
akgl_RectanglePoints points;
|
||||
// Zeroed for the same reason as the fixtures in
|
||||
// test_akgl_collide_point_rectangle_nullpointers: the last case here is a
|
||||
// real call, and feeding it stack garbage is noise under `memcheck`.
|
||||
SDL_FRect testrect = {.x = 0, .y = 0, .w = 0, .h = 0};
|
||||
PREPARE_ERROR(errctx);
|
||||
|
||||
memset((void *)&points, 0x00, sizeof(akgl_RectanglePoints));
|
||||
|
||||
ATTEMPT {
|
||||
CATCH(errctx, akgl_rectangle_points(NULL, NULL));
|
||||
FAIL_BREAK(errctx, AKGL_ERR_BEHAVIOR, "akgl_rectangle_points fails to FAIL with all NULL pointers");
|
||||
} CLEANUP {
|
||||
} PROCESS(errctx) {
|
||||
} HANDLE(errctx, AKERR_NULLPOINTER) {
|
||||
// noop
|
||||
} FINISH(errctx, true);
|
||||
|
||||
ATTEMPT {
|
||||
CATCH(errctx, akgl_rectangle_points(NULL, &testrect));
|
||||
FAIL_BREAK(errctx, AKGL_ERR_BEHAVIOR, "akgl_rectangle_points fails to FAIL with NULL SDL_FRect pointer");
|
||||
} CLEANUP {
|
||||
} PROCESS(errctx) {
|
||||
} HANDLE(errctx, AKERR_NULLPOINTER) {
|
||||
// noop
|
||||
} FINISH(errctx, true);
|
||||
|
||||
ATTEMPT {
|
||||
CATCH(errctx, akgl_rectangle_points(&points, NULL));
|
||||
FAIL_BREAK(errctx, AKGL_ERR_BEHAVIOR, "akgl_rectangle_points fails to FAIL with NULL akgl_RectanglePoints pointer");
|
||||
} CLEANUP {
|
||||
} PROCESS(errctx) {
|
||||
} HANDLE(errctx, AKERR_NULLPOINTER) {
|
||||
// noop
|
||||
} FINISH(errctx, true);
|
||||
|
||||
ATTEMPT {
|
||||
CATCH(errctx, akgl_rectangle_points(&points, &testrect));
|
||||
} CLEANUP {
|
||||
} PROCESS(errctx) {
|
||||
} FINISH(errctx, true);
|
||||
|
||||
SUCCEED_RETURN(errctx);
|
||||
}
|
||||
|
||||
akerr_ErrorContext *test_akgl_rectangle_points_math(void)
|
||||
{
|
||||
akgl_RectanglePoints points;
|
||||
SDL_FRect testrect = {.x = 0, .y = 0, .w = 32, .h = 32};
|
||||
memset((void *)&points, 0x00, sizeof(akgl_RectanglePoints));
|
||||
|
||||
PREPARE_ERROR(errctx);
|
||||
ATTEMPT {
|
||||
CATCH(errctx, akgl_rectangle_points(&points, &testrect));
|
||||
if ( points.topleft.x != 0 ||
|
||||
points.topleft.y != 0 ||
|
||||
points.topright.x != 32 ||
|
||||
points.topright.y != 0 ||
|
||||
points.bottomleft.x != 0 ||
|
||||
points.bottomleft.y != 32 ||
|
||||
points.bottomright.x != 32 ||
|
||||
points.bottomright.y != 32 ) {
|
||||
FAIL_BREAK(
|
||||
errctx,
|
||||
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,
|
||||
points.bottomleft.x, points.bottomleft.y,
|
||||
points.bottomright.x, points.bottomright.y
|
||||
);
|
||||
}
|
||||
} CLEANUP {
|
||||
} PROCESS(errctx) {
|
||||
} FINISH(errctx, true);
|
||||
SUCCEED_RETURN(errctx);
|
||||
}
|
||||
|
||||
akerr_ErrorContext *test_akgl_collide_point_rectangle_nullpointers(void)
|
||||
{
|
||||
// Zeroed rather than left as whatever the stack held. The last case in this
|
||||
// function is a real call with real arguments, and reading uninitialised
|
||||
// floats out of it is sixteen findings under `memcheck` for a test that is
|
||||
// not about coordinates at all.
|
||||
akgl_Point testpoint = { .x = 0, .y = 0 };
|
||||
akgl_RectanglePoints testrectpoints;
|
||||
bool testcollide = false;
|
||||
|
||||
PREPARE_ERROR(errctx);
|
||||
|
||||
memset(&testrectpoints, 0x00, sizeof(akgl_RectanglePoints));
|
||||
|
||||
ATTEMPT {
|
||||
CATCH(errctx, akgl_collide_point_rectangle(&testpoint, &testrectpoints, NULL));
|
||||
FAIL_BREAK(errctx, AKGL_ERR_BEHAVIOR, "akgl_collide_point_rectangle(*, *, NULL) failed");
|
||||
} CLEANUP {
|
||||
} PROCESS(errctx) {
|
||||
} HANDLE(errctx, AKERR_NULLPOINTER) {
|
||||
// noop
|
||||
} FINISH(errctx, true);
|
||||
|
||||
ATTEMPT {
|
||||
CATCH(errctx, akgl_collide_point_rectangle(&testpoint, NULL, &testcollide));
|
||||
FAIL_BREAK(errctx, AKGL_ERR_BEHAVIOR, "akgl_collide_point_rectangle(*, NULL, *) failed");
|
||||
} CLEANUP {
|
||||
} PROCESS(errctx) {
|
||||
} HANDLE(errctx, AKERR_NULLPOINTER) {
|
||||
// noop
|
||||
} FINISH(errctx, true);
|
||||
|
||||
ATTEMPT {
|
||||
CATCH(errctx, akgl_collide_point_rectangle(NULL, &testrectpoints, &testcollide));
|
||||
FAIL_BREAK(errctx, AKGL_ERR_BEHAVIOR, "akgl_collide_point_rectangle(NULL, *, *) failed");
|
||||
} CLEANUP {
|
||||
} PROCESS(errctx) {
|
||||
} HANDLE(errctx, AKERR_NULLPOINTER) {
|
||||
// noop
|
||||
} FINISH(errctx, true);
|
||||
|
||||
ATTEMPT {
|
||||
CATCH(errctx, akgl_collide_point_rectangle(NULL, NULL, NULL));
|
||||
FAIL_BREAK(errctx, AKGL_ERR_BEHAVIOR, "akgl_collide_point_rectangle(NULL, NULL, NULL) failed");
|
||||
} CLEANUP {
|
||||
} PROCESS(errctx) {
|
||||
} HANDLE(errctx, AKERR_NULLPOINTER) {
|
||||
// noop
|
||||
} FINISH(errctx, true);
|
||||
|
||||
ATTEMPT {
|
||||
CATCH(errctx, akgl_collide_point_rectangle(&testpoint, &testrectpoints, &testcollide));
|
||||
} CLEANUP {
|
||||
} PROCESS(errctx) {
|
||||
} FINISH(errctx, true);
|
||||
|
||||
SUCCEED_RETURN(errctx);
|
||||
}
|
||||
|
||||
akerr_ErrorContext *test_akgl_collide_point_rectangle_logic(void)
|
||||
{
|
||||
akgl_Point testpoint = {.x = 16, .y = 16};
|
||||
SDL_FRect testrect = { .x = 0, .y = 0, .w = 32, .h = 32};
|
||||
akgl_RectanglePoints testrectpoints;
|
||||
bool testcollide = false;
|
||||
PREPARE_ERROR(errctx);
|
||||
|
||||
ATTEMPT {
|
||||
CATCH(errctx, akgl_rectangle_points(&testrectpoints, &testrect));
|
||||
CATCH(errctx, akgl_collide_point_rectangle(&testpoint, &testrectpoints, &testcollide));
|
||||
if ( testcollide == false ) {
|
||||
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, AKGL_ERR_BEHAVIOR, "Invalid collision reported");
|
||||
}
|
||||
} CLEANUP {
|
||||
} PROCESS(errctx) {
|
||||
} FINISH(errctx, true);
|
||||
SUCCEED_RETURN(errctx);
|
||||
}
|
||||
|
||||
akerr_ErrorContext *test_akgl_collide_rectangles_nullpointers(void)
|
||||
{
|
||||
SDL_FRect testrect1 = {.x = 0, .y = 0, .w = 0, .h = 0};
|
||||
@@ -256,12 +90,12 @@ akerr_ErrorContext *test_akgl_collide_rectangles_nullpointers(void)
|
||||
* corner tests all report false. That was documented on akgl_collide_rectangles
|
||||
* as a known limitation rather than fixed, and there was no test for it.
|
||||
*
|
||||
* The three cases below the cross are the ones a rewrite can break while fixing
|
||||
* it: touching edges must keep counting as a collision, because
|
||||
* akgl_collide_point_rectangle is inclusive on all four edges and both headers
|
||||
* promise it; full containment must keep working; and a separation of less than
|
||||
* one pixel must be seen, which the old implementation could not do because it
|
||||
* routed through akgl_Point and truncated float to int.
|
||||
* The three cases below the cross are the ones the rewrite could have broken
|
||||
* while fixing it: touching edges must keep counting as a collision, because the
|
||||
* corner form was inclusive on all four edges and the header promised it; full
|
||||
* containment must keep working; and a separation of less than one pixel must be
|
||||
* seen, which the old implementation could not do because it routed through the
|
||||
* since-removed akgl_Point and truncated float to int.
|
||||
*/
|
||||
akerr_ErrorContext *test_akgl_collide_rectangles_arrangements(void)
|
||||
{
|
||||
@@ -295,8 +129,7 @@ akerr_ErrorContext *test_akgl_collide_rectangles_arrangements(void)
|
||||
CATCH(errctx, akgl_collide_rectangles(&inner, &outer, &collide));
|
||||
TEST_ASSERT(errctx, (collide == true), "a containing rectangle was missed");
|
||||
|
||||
// A shared edge and nothing more. akgl_collide_point_rectangle is
|
||||
// inclusive on all four edges, so touching counts; util.h and chapter 18
|
||||
// A shared edge and nothing more. Touching counts; util.h and chapter 19
|
||||
// both say so, and a span test written with < rather than <= silently
|
||||
// changes that.
|
||||
CATCH(errctx, akgl_collide_rectangles(&left, &right, &collide));
|
||||
@@ -540,12 +373,6 @@ int main(void)
|
||||
PREPARE_ERROR(errctx);
|
||||
ATTEMPT {
|
||||
CATCH(errctx, akgl_error_init());
|
||||
CATCH(errctx, test_akgl_rectangle_points_nullpointers());
|
||||
CATCH(errctx, test_akgl_rectangle_points_math());
|
||||
CATCH(errctx, test_akgl_collide_point_rectangle_nullpointers());
|
||||
// Defined since forever and never called until 0.5.0. TODO.md, "Known
|
||||
// and still open" item 9.
|
||||
CATCH(errctx, test_akgl_collide_point_rectangle_logic());
|
||||
CATCH(errctx, test_akgl_collide_rectangles_nullpointers());
|
||||
CATCH(errctx, test_akgl_collide_rectangles_logic());
|
||||
CATCH(errctx, test_akgl_collide_rectangles_arrangements());
|
||||
|
||||
Reference in New Issue
Block a user