Testing time (and found some bugs!)
This commit is contained in:
9
test/time/CMakeLists.txt
Normal file
9
test/time/CMakeLists.txt
Normal file
@@ -0,0 +1,9 @@
|
||||
# Copyright (c) 2026 Dominic Masters
|
||||
#
|
||||
# This software is released under the MIT License.
|
||||
# https://opensource.org/licenses/MIT
|
||||
|
||||
include(dusktest)
|
||||
|
||||
# Tests
|
||||
dusktest(test_time.c)
|
||||
122
test/time/test_time.c
Normal file
122
test/time/test_time.c
Normal file
@@ -0,0 +1,122 @@
|
||||
/**
|
||||
* Copyright (c) 2026 Dominic Masters
|
||||
*
|
||||
* This software is released under the MIT License.
|
||||
* https://opensource.org/licenses/MIT
|
||||
*/
|
||||
|
||||
#include "dusktest.h"
|
||||
#include <SDL2/SDL.h>
|
||||
|
||||
// Mocks
|
||||
static uint64_t SDL_GETTICKS_TICKS = 0;
|
||||
static bool_t SDL_GETTICKS_CALLED = false;
|
||||
|
||||
uint64_t SDL_GetTicks64(void) {
|
||||
SDL_GETTICKS_CALLED = true;
|
||||
return SDL_GETTICKS_TICKS;
|
||||
}
|
||||
|
||||
// Mocked includes
|
||||
#include "util/memory.h"
|
||||
#include "time/time.h"
|
||||
|
||||
// Tests
|
||||
static void test_timeInit(void **state) {
|
||||
(void)state;
|
||||
|
||||
// Fill time with garbage
|
||||
memorySet(&TIME, 0xFF, sizeof(TIME));
|
||||
|
||||
// Init
|
||||
timeInit();
|
||||
|
||||
// Inital struct is set.
|
||||
assert_float_equal(TIME.time, TIME_STEP, 0.0001f);
|
||||
assert_float_equal(TIME.delta, TIME_STEP, 0.0001f);
|
||||
assert_float_equal(TIME.dynamicTime, TIME_STEP, 0.0001f);
|
||||
assert_float_equal(TIME.dynamicDelta, TIME_STEP, 0.0001f);
|
||||
assert_false(TIME.dynamicUpdate);
|
||||
}
|
||||
|
||||
static void test_timeUpdate(void **state) {
|
||||
(void)state;
|
||||
|
||||
// Init first
|
||||
timeInit();
|
||||
|
||||
// First time update, calls SDL_GetTicks
|
||||
SDL_GETTICKS_TICKS = 14; // Simulate 15ms elapsed (just barely not one step)
|
||||
SDL_GETTICKS_CALLED = false;
|
||||
timeUpdate();
|
||||
assert_true(SDL_GETTICKS_CALLED);
|
||||
assert_true(TIME.dynamicUpdate);
|
||||
assert_float_equal(TIME.dynamicDelta, 0.014f, 0.0001f);
|
||||
assert_float_equal(TIME.dynamicTime, TIME_STEP + TIME.dynamicDelta, 0.0001f);
|
||||
assert_float_equal(TIME.delta, TIME_STEP, 0.0001f); // Not changed
|
||||
assert_float_equal(TIME.time, TIME_STEP, 0.0001f); // Not changed
|
||||
|
||||
// Simulate total 16ms elapsed (2ms more)
|
||||
SDL_GETTICKS_TICKS = 16;
|
||||
SDL_GETTICKS_CALLED = false;
|
||||
timeUpdate();
|
||||
assert_true(SDL_GETTICKS_CALLED);
|
||||
assert_false(TIME.dynamicUpdate);
|
||||
assert_float_equal(TIME.dynamicDelta, 0.002f, 0.0001f);
|
||||
assert_float_equal(TIME.dynamicTime, TIME_STEP * 2, 0.0001f);
|
||||
assert_float_equal(TIME.delta, TIME_STEP, 0.0001f);
|
||||
assert_float_equal(TIME.time, TIME_STEP * 2, 0.0001f); // Stepped once
|
||||
|
||||
// Second test, half step (16 + 8)
|
||||
SDL_GETTICKS_TICKS = 24;
|
||||
SDL_GETTICKS_CALLED = false;
|
||||
timeUpdate();
|
||||
assert_true(SDL_GETTICKS_CALLED);
|
||||
assert_true(TIME.dynamicUpdate);
|
||||
assert_float_equal(TIME.dynamicDelta, 0.008f, 0.0001f);
|
||||
assert_float_equal(TIME.dynamicTime, TIME_STEP + 0.024f, 0.0001f);
|
||||
assert_float_equal(TIME.delta, TIME_STEP, 0.0001f);
|
||||
assert_float_equal(TIME.time, TIME_STEP * 2, 0.0001f);// Unchanged.
|
||||
|
||||
// Third test, another half step, leading to non dynamic update
|
||||
SDL_GETTICKS_TICKS = 32;
|
||||
SDL_GETTICKS_CALLED = false;
|
||||
timeUpdate();
|
||||
assert_true(SDL_GETTICKS_CALLED);
|
||||
assert_false(TIME.dynamicUpdate);
|
||||
assert_float_equal(TIME.dynamicDelta, 0.008f, 0.0001f);
|
||||
assert_float_equal(TIME.dynamicTime, TIME_STEP + 0.032f, 0.0001f);
|
||||
assert_float_equal(TIME.delta, TIME_STEP, 0.0001f);
|
||||
assert_float_equal(TIME.time, TIME_STEP * 3, 0.0001f);
|
||||
|
||||
// Fourth test, large jump, should only step once
|
||||
SDL_GETTICKS_TICKS = 100; // Simulate 100ms elapsed
|
||||
SDL_GETTICKS_CALLED = false;
|
||||
timeUpdate();
|
||||
assert_true(SDL_GETTICKS_CALLED);
|
||||
assert_false(TIME.dynamicUpdate);
|
||||
assert_float_equal(TIME.dynamicDelta, 0.068f, 0.0001f);
|
||||
assert_float_equal(TIME.dynamicTime, TIME_STEP + 0.100f, 0.0001f);
|
||||
assert_float_equal(TIME.delta, TIME_STEP, 0.0001f);
|
||||
assert_float_equal(TIME.time, TIME_STEP * 4, 0.0001f);
|
||||
|
||||
// Fifth test, despite a small time passing the game should be trying to catch
|
||||
// and running extra ticks
|
||||
SDL_GETTICKS_TICKS = 104; // Simulate 4ms elapsed
|
||||
SDL_GETTICKS_CALLED = false;
|
||||
timeUpdate();
|
||||
assert_true(SDL_GETTICKS_CALLED);
|
||||
assert_false(TIME.dynamicUpdate);
|
||||
assert_float_equal(TIME.dynamicDelta, 0.004f, 0.0001f);
|
||||
assert_float_equal(TIME.dynamicTime, TIME_STEP + 0.104f, 0.0001f);
|
||||
assert_float_equal(TIME.delta, TIME_STEP, 0.0001f);
|
||||
assert_float_equal(TIME.time, TIME_STEP * 5, 0.0001f);
|
||||
}
|
||||
|
||||
int main(int argc, char **argv) {
|
||||
const struct CMUnitTest tests[] = {
|
||||
cmocka_unit_test(test_timeInit),
|
||||
cmocka_unit_test(test_timeUpdate),
|
||||
};
|
||||
return cmocka_run_group_tests(tests, NULL, NULL);
|
||||
}
|
||||
Reference in New Issue
Block a user