Testing time (and found some bugs!)
This commit is contained in:
@@ -33,16 +33,18 @@ void timeUpdate(void) {
|
|||||||
|
|
||||||
#if TIME_FIXED == 0
|
#if TIME_FIXED == 0
|
||||||
#if TIME_SDL2
|
#if TIME_SDL2
|
||||||
float_t newTime = (float_t)SDL_GetTicks() / 1000.0f;
|
float_t msElapsed = ((float_t)SDL_GetTicks64() / 1000.0f) + TIME_STEP;
|
||||||
TIME.dynamicDelta = newTime - TIME.dynamicTime;
|
TIME.dynamicDelta = msElapsed - TIME.dynamicTime;
|
||||||
TIME.dynamicTime = newTime;
|
TIME.dynamicTime = msElapsed;
|
||||||
TIME.dynamicUpdate = true;
|
TIME.dynamicUpdate = true;
|
||||||
#else
|
#else
|
||||||
#error "No time platform defined"
|
#error "No time platform defined"
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
assertTrue(TIME.dynamicDelta >= 0.0f, "Time delta is negative");
|
assertTrue(TIME.dynamicDelta >= 0.0f, "Time delta is negative");
|
||||||
if(TIME.dynamicTime - TIME.time >= TIME_STEP) {
|
|
||||||
|
// Is within 1ms of a full step?
|
||||||
|
if(TIME.dynamicTime - TIME.time >= TIME_STEP * 0.999f) {
|
||||||
TIME.dynamicUpdate = false;
|
TIME.dynamicUpdate = false;
|
||||||
TIME.delta = TIME_STEP;
|
TIME.delta = TIME_STEP;
|
||||||
TIME.time += TIME_STEP;
|
TIME.time += TIME_STEP;
|
||||||
|
|||||||
@@ -8,8 +8,7 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
#include "dusk.h"
|
#include "dusk.h"
|
||||||
|
|
||||||
#define TIME_STEP (1.0f / 60.0f) // 60 Ticks per second (what we are aiming for)
|
#define TIME_STEP (16.0f / 1000.0f)
|
||||||
|
|
||||||
#ifndef TIME_FIXED
|
#ifndef TIME_FIXED
|
||||||
#define TIME_FIXED 0
|
#define TIME_FIXED 0
|
||||||
#endif
|
#endif
|
||||||
|
|||||||
@@ -3,4 +3,5 @@
|
|||||||
# This software is released under the MIT License.
|
# This software is released under the MIT License.
|
||||||
# https://opensource.org/licenses/MIT
|
# https://opensource.org/licenses/MIT
|
||||||
|
|
||||||
|
add_subdirectory(time)
|
||||||
add_subdirectory(util)
|
add_subdirectory(util)
|
||||||
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