Files
dusk/test/rpg/cutscene/test_cutscenecontrol.c
T
YourWishes 1bd73d69fe Clamp keyframe interpolation to last value, add main menu scene/UI, battle HUD, and expanded test coverage
- 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
2026-08-06 12:58:07 -05:00

143 lines
4.0 KiB
C

/**
* Copyright (c) 2026 Dominic Masters
*
* This software is released under the MIT License.
* https://opensource.org/licenses/MIT
*/
#include "dusktest.h"
#include "rpg/cutscene/cutscenesystem.h"
#include "time/time.h"
#include "util/memory.h"
static void test_cutsceneWaitCompletesAfterItsDuration(void **state) {
cutsceneitem_t item = CUTSCENE_WAIT(1.0f);
cutsceneitemdata_t data;
memoryZero(&data, sizeof(data));
cutsceneWaitStart(&item, &data);
TIME.delta = 0.5f;
assert_false(cutsceneWaitUpdate(&item, &data));
TIME.delta = 0.6f;
assert_true(cutsceneWaitUpdate(&item, &data));
}
static void *lastUserData;
static uint8_t callbackCallCount;
static void recordCallback(void *userData) {
lastUserData = userData;
callbackCallCount++;
}
static void test_cutsceneCallbackFiresOnStartWithUserData(void **state) {
callbackCallCount = 0;
lastUserData = NULL;
cutsceneitem_t item = CUTSCENE_CALLBACK(recordCallback);
cutsceneitemdata_t data;
cutsceneCallbackStart(&item, &data);
assert_int_equal(callbackCallCount, 1);
assert_ptr_equal(lastUserData, CUTSCENE_SYSTEM.userData);
// Callback items always complete immediately -- the effect already
// happened in Start, not Update.
assert_true(cutsceneCallbackUpdate(&item, &data));
assert_int_equal(callbackCallCount, 1);// Update doesn't fire it again
}
static void test_cutsceneCallbackNullIsNoop(void **state) {
callbackCallCount = 0;
cutsceneitem_t item = { .type = CUTSCENE_ITEM_TYPE_CALLBACK, .callback = NULL };
cutsceneitemdata_t data;
cutsceneCallbackStart(&item, &data);// should not crash
assert_int_equal(callbackCallCount, 0);
}
static void test_cutsceneSetPauseAppliesImmediately(void **state) {
CUTSCENE_SYSTEM.pause = CUTSCENE_PAUSE_NONE;
cutsceneitem_t item =
CUTSCENE_SET_PAUSE(CUTSCENE_PAUSE_NPC | CUTSCENE_PAUSE_BATTLE);
cutsceneitemdata_t data;
cutsceneSetPauseStart(&item, &data);
assert_int_equal(
CUTSCENE_SYSTEM.pause, CUTSCENE_PAUSE_NPC | CUTSCENE_PAUSE_BATTLE
);
assert_true(cutsceneSetPauseUpdate(&item, &data));
}
static void test_cutsceneConcurrentCompletesOnceAllChildrenDo(void **state) {
cutsceneitem_t item = CUTSCENE_CONCURRENT(
CUTSCENE_WAIT(0.2f),
CUTSCENE_WAIT(0.5f)
);
cutsceneitemdata_t data;
memoryZero(&data, sizeof(data));
cutsceneConcurrentStart(&item, &data);
TIME.delta = 0.3f;
// Child 0 (0.2s) elapses; child 1 (0.5s) still has 0.2s left.
assert_false(cutsceneConcurrentUpdate(&item, &data));
TIME.delta = 0.3f;
// Child 1 now elapses too.
assert_true(cutsceneConcurrentUpdate(&item, &data));
}
static void test_cutsceneConcurrentDoesNotReUpdateFinishedChildren(
void **state
) {
cutsceneitem_t item = CUTSCENE_CONCURRENT(
CUTSCENE_WAIT(0.1f),
CUTSCENE_WAIT(10.0f)
);
cutsceneitemdata_t data;
memoryZero(&data, sizeof(data));
cutsceneConcurrentStart(&item, &data);
TIME.delta = 0.2f;
cutsceneConcurrentUpdate(&item, &data);// child 0 finishes
// If child 0 were re-updated, its stored wait value would keep dropping
// further below zero -- not observable directly, but the overall result
// must not falsely report done just because child 0 keeps completing.
TIME.delta = 0.2f;
assert_false(cutsceneConcurrentUpdate(&item, &data));
}
static void test_cutsceneConcurrentCannotNest(void **state) {
cutsceneitem_t outer =
CUTSCENE_CONCURRENT(CUTSCENE_CONCURRENT(CUTSCENE_WAIT(1.0f)));
cutsceneitemdata_t data;
expect_assert_failure(cutsceneConcurrentStart(&outer, &data));
}
int main(int argc, char** argv) {
const struct CMUnitTest tests[] = {
cmocka_unit_test(test_cutsceneWaitCompletesAfterItsDuration),
cmocka_unit_test(test_cutsceneCallbackFiresOnStartWithUserData),
cmocka_unit_test(test_cutsceneCallbackNullIsNoop),
cmocka_unit_test(test_cutsceneSetPauseAppliesImmediately),
cmocka_unit_test(test_cutsceneConcurrentCompletesOnceAllChildrenDo),
cmocka_unit_test(test_cutsceneConcurrentDoesNotReUpdateFinishedChildren),
cmocka_unit_test(test_cutsceneConcurrentCannotNest),
};
return cmocka_run_group_tests(tests, NULL, NULL);
}