From 48422e313b31b79d76dd8f027b4d934994168859 Mon Sep 17 00:00:00 2001 From: 3gg <3gg@shellblade.net> Date: Sun, 26 Apr 2026 13:06:44 -0700 Subject: Test for catch-up. Document --- simloop/test/simloop_test.c | 54 +++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 54 insertions(+) (limited to 'simloop/test/simloop_test.c') diff --git a/simloop/test/simloop_test.c b/simloop/test/simloop_test.c index 50e0852..790ad73 100644 --- a/simloop/test/simloop_test.c +++ b/simloop/test/simloop_test.c @@ -250,4 +250,58 @@ TEST_CASE(simloop_determinism) { TEST_EQUAL(sim[0].sum, sim[1].sum); } +/// The simulation loop attempts to catch up with the clock in the event of a +/// time spike. This is possible only if the simulation loops with a frequency +/// higher than the requested update frequency given by the update delta time. +static void simloop_catch_up( + struct test_case_metadata* metadata, int update_ddt_ms, int loop_step_ms, + bool expect_catchup) { + const int UPDATE_FPS = 1000 / update_ddt_ms; + const simloop_time_t UPDATE_DDT = + time_delta_from_sec(1.0 / (double)UPDATE_FPS); + const simloop_time_t STEP = + time_delta_from_sec((double)loop_step_ms / 1000.0); + const simloop_time_t SIM_DURATION_SEC = time_delta_from_sec(30); + const int EXPECTED_TOTAL_FRAMES_WITH_CATCHUP = + (int)(SIM_DURATION_SEC / UPDATE_DDT); + + Simloop simloop = simloop_make(&(SimloopArgs){.update_fps = UPDATE_FPS}); + SimloopOut simout; + int frames = 0; + + // Simulate a time spike. + // Advance time to t=10s. That is a lag of 10,000ms / 100ms = 100 frames. + // The simulation now has 20s to catch up. + simloop_time_t dt = time_delta_from_sec(10); + for (simloop_time_t t = dt; t <= SIM_DURATION_SEC;) { + simloop_update(&simloop, dt, &simout); + + if (simout.should_update) { + frames++; + } + + // New delta is as usual. + dt = STEP; + t += dt; + } + + if (expect_catchup) { + TEST_EQUAL(frames, EXPECTED_TOTAL_FRAMES_WITH_CATCHUP); + } else { + TEST_TRUE(frames < EXPECTED_TOTAL_FRAMES_WITH_CATCHUP); + } +} +/// (Loop frequency > update frequency) => successful catch-up. +TEST_CASE(simloop_catch_up_success) { + constexpr int UPDATE_DDT_MS = 100; + constexpr int LOOP_DDT_MS = 10; + simloop_catch_up(metadata, UPDATE_DDT_MS, LOOP_DDT_MS, true); +} +/// (Loop frequency < update frequency) => failed catch-up. +TEST_CASE(simloop_catch_up_failure) { + constexpr int UPDATE_DDT_MS = 10; + constexpr int LOOP_DDT_MS = 100; + simloop_catch_up(metadata, UPDATE_DDT_MS, LOOP_DDT_MS, false); +} + int main() { return 0; } -- cgit v1.2.3