1bd73d69fe
- keyframeGetValue now returns the last keyframe's value for times at or beyond it, fixes a missing util/math.h include, and asserts keyframes are sorted by time; adds test/animation/test_keyframe.c - Adds mainmenu scene/UI and a battle HUD UI frame - Adds save autosave-related fields and battle scene tweaks - Adds headless test coverage for cutscenes, entities, and map areas
134 lines
3.8 KiB
C
134 lines
3.8 KiB
C
/**
|
|
* Copyright (c) 2026 Dominic Masters
|
|
*
|
|
* This software is released under the MIT License.
|
|
* https://opensource.org/licenses/MIT
|
|
*/
|
|
|
|
#include "dusktest.h"
|
|
#include "entitytestfixture.h"
|
|
#include "ui/rpg/textbox/uitextboxmain.h"
|
|
#include "ui/focus/uifocus.h"
|
|
#include "rpg/cutscene/cutscenesystem.h"
|
|
|
|
static const cutsceneitem_t CUTSCENE_TEST_INTERACT_ITEMS[] = {
|
|
CUTSCENE_WAIT(1.0f)
|
|
};
|
|
static const cutscene_t CUTSCENE_TEST_INTERACT = {
|
|
.items = CUTSCENE_TEST_INTERACT_ITEMS,
|
|
.itemCount = 1,
|
|
.pause = CUTSCENE_PAUSE_NONE,
|
|
.dataSize = 0
|
|
};
|
|
|
|
static entity_t *player;
|
|
static entity_t *target;
|
|
|
|
static void resetInteractFixture(void) {
|
|
entityTestFixtureReset();
|
|
uiFocusInit();
|
|
uiTextboxMainInit();
|
|
uiTextboxMainFocusClosed(NULL);// force-clear stale focus from a prior test
|
|
cutsceneSystemInit();
|
|
|
|
entityInit(&ENTITIES[0], ENTITY_TYPE_PLAYER);
|
|
entityInit(&ENTITIES[1], ENTITY_TYPE_NPC);
|
|
player = &ENTITIES[0];
|
|
target = &ENTITIES[1];
|
|
player->direction = ENTITY_DIR_NORTH;
|
|
}
|
|
|
|
static void test_entityInteractWithNull(void **state) {
|
|
|
|
resetInteractFixture();
|
|
|
|
target->interact.type = ENTITY_INTERACT_NULL;
|
|
entityInteractWith(player, target);// should not crash or change anything
|
|
assert_int_equal(target->interact.type, ENTITY_INTERACT_NULL);
|
|
}
|
|
|
|
static void test_entityInteractWithPrintTurnsNpcToFacePlayer(void **state) {
|
|
|
|
resetInteractFixture();
|
|
|
|
target->interact.type = ENTITY_INTERACT_PRINT;
|
|
target->interact.data.message = "Hello!";
|
|
|
|
entityInteractWith(player, target);
|
|
|
|
assert_true(uiTextboxMainIsActive());
|
|
assert_int_equal(target->data.npc.interactState, NPC_INTERACT_STATE_CONVERSING);
|
|
// NPC turns to face the opposite of the player's facing direction.
|
|
assert_int_equal(target->direction, entityDirGetOpposite(player->direction));
|
|
}
|
|
|
|
static entity_t *callbackPlayerArg;
|
|
static entity_t *callbackTargetArg;
|
|
static uint8_t callbackCount;
|
|
|
|
static void recordInteractCallback(entity_t *p, entity_t *t) {
|
|
callbackPlayerArg = p;
|
|
callbackTargetArg = t;
|
|
callbackCount++;
|
|
}
|
|
|
|
static void test_entityInteractWithCallback(void **state) {
|
|
|
|
resetInteractFixture();
|
|
callbackCount = 0;
|
|
|
|
target->interact.type = ENTITY_INTERACT_CALLBACK;
|
|
target->interact.data.callback = recordInteractCallback;
|
|
|
|
entityInteractWith(player, target);
|
|
|
|
assert_int_equal(callbackCount, 1);
|
|
assert_ptr_equal(callbackPlayerArg, player);
|
|
assert_ptr_equal(callbackTargetArg, target);
|
|
}
|
|
|
|
static void test_entityInteractWithCallbackRequiresNonNull(void **state) {
|
|
|
|
resetInteractFixture();
|
|
|
|
target->interact.type = ENTITY_INTERACT_CALLBACK;
|
|
target->interact.data.callback = NULL;
|
|
|
|
expect_assert_failure(entityInteractWith(player, target));
|
|
}
|
|
|
|
static void test_entityInteractWithCutsceneStartsIt(void **state) {
|
|
|
|
resetInteractFixture();
|
|
|
|
target->interact.type = ENTITY_INTERACT_CUTSCENE;
|
|
target->interact.data.cutscene = &CUTSCENE_TEST_INTERACT;
|
|
|
|
entityInteractWith(player, target);
|
|
|
|
assert_ptr_equal(CUTSCENE_SYSTEM.scene, &CUTSCENE_TEST_INTERACT);
|
|
assert_ptr_equal(CUTSCENE_SYSTEM.entityInteract, player);
|
|
assert_ptr_equal(CUTSCENE_SYSTEM.entityInteracted, target);
|
|
}
|
|
|
|
static void test_entityInteractWithRequiresNonNullEntities(void **state) {
|
|
|
|
resetInteractFixture();
|
|
|
|
expect_assert_failure(entityInteractWith(NULL, target));
|
|
expect_assert_failure(entityInteractWith(player, NULL));
|
|
}
|
|
|
|
int main(int argc, char** argv) {
|
|
const struct CMUnitTest tests[] = {
|
|
cmocka_unit_test(test_entityInteractWithNull),
|
|
cmocka_unit_test(test_entityInteractWithPrintTurnsNpcToFacePlayer),
|
|
cmocka_unit_test(test_entityInteractWithCallback),
|
|
cmocka_unit_test(test_entityInteractWithCallbackRequiresNonNull),
|
|
cmocka_unit_test(test_entityInteractWithCutsceneStartsIt),
|
|
cmocka_unit_test(test_entityInteractWithRequiresNonNullEntities),
|
|
};
|
|
|
|
return cmocka_run_group_tests(tests, NULL, NULL);
|
|
}
|