diff options
Diffstat (limited to 'simloop/test')
| -rw-r--r-- | simloop/test/simloop_test.c | 69 |
1 files changed, 20 insertions, 49 deletions
diff --git a/simloop/test/simloop_test.c b/simloop/test/simloop_test.c index 790ad73..61e7dff 100644 --- a/simloop/test/simloop_test.c +++ b/simloop/test/simloop_test.c | |||
| @@ -29,65 +29,38 @@ static uint64_t xorshift64(XorShift64State* state) { | |||
| 29 | // ----------------------------------------------------------------------------- | 29 | // ----------------------------------------------------------------------------- |
| 30 | // Tests. | 30 | // Tests. |
| 31 | 31 | ||
| 32 | /// At time/frame 0: | 32 | /// At time/frame 0, no update is triggered (not enough time passed). |
| 33 | /// 1. An initial render is always triggered. | ||
| 34 | /// 2. No update is triggered (not enough time passed). | ||
| 35 | TEST_CASE(simloop_initial_render) { | 33 | TEST_CASE(simloop_initial_render) { |
| 36 | Simloop simloop = simloop_make(&(SimloopArgs){.update_fps = 10}); | 34 | Simloop simloop = simloop_make(&(SimloopArgs){.update_fps = 10}); |
| 37 | SimloopOut simout; | 35 | SimloopOut simout; |
| 38 | 36 | ||
| 39 | simloop_update(&simloop, 0, &simout); | 37 | simloop_update(&simloop, 0, &simout); |
| 40 | 38 | ||
| 41 | TEST_TRUE(simout.should_render); | ||
| 42 | TEST_TRUE(!simout.should_update); | 39 | TEST_TRUE(!simout.should_update); |
| 43 | TEST_EQUAL(simout.frame, 0); | 40 | TEST_EQUAL(simout.frame, 0); |
| 44 | } | 41 | } |
| 45 | 42 | ||
| 46 | /// A frame is not re-rendered if time does not advance. | 43 | /// The simulation is not updated if time does not advance. |
| 47 | /// This applies whether rendering is frame-rate capped or unlimited, and | 44 | /// This applies generally to any time > 0. |
| 48 | /// whether we are in the initial frame or a subsequent one. | 45 | TEST_CASE(simloop_render_not_retriggered) { |
| 49 | void simloop_render_not_retriggered( | 46 | Simloop simloop = simloop_make(&(SimloopArgs){.update_fps = 10}); |
| 50 | struct test_case_metadata* metadata, int max_render_fps, | ||
| 51 | bool initial_frame) { | ||
| 52 | Simloop simloop = simloop_make( | ||
| 53 | &(SimloopArgs){.update_fps = 10, .max_render_fps = max_render_fps}); | ||
| 54 | SimloopOut simout; | 47 | SimloopOut simout; |
| 55 | 48 | ||
| 49 | // Advance time by some amount to get past t=0. | ||
| 50 | simloop_update(&simloop, 1, &simout); | ||
| 51 | |||
| 52 | // Now "advance" by 0. | ||
| 53 | const uint64_t frame_before = simout.frame; | ||
| 56 | simloop_update(&simloop, 0, &simout); | 54 | simloop_update(&simloop, 0, &simout); |
| 55 | const uint64_t frame_after = simout.frame; | ||
| 57 | 56 | ||
| 58 | TEST_TRUE(simout.should_render); | ||
| 59 | TEST_TRUE(!simout.should_update); | 57 | TEST_TRUE(!simout.should_update); |
| 60 | TEST_EQUAL(simout.frame, 0); | 58 | TEST_EQUAL(frame_before, frame_after); |
| 61 | |||
| 62 | if (!initial_frame) { | ||
| 63 | // Advance time beyond the initial frame. | ||
| 64 | simloop_update(&simloop, 1, &simout); | ||
| 65 | } | ||
| 66 | |||
| 67 | for (int i = 0; i < 10; i++) { | ||
| 68 | // Note that time does not advance here. | ||
| 69 | simloop_update(&simloop, 0, &simout); | ||
| 70 | TEST_TRUE(!simout.should_render); | ||
| 71 | TEST_TRUE(!simout.should_update); | ||
| 72 | TEST_EQUAL(simout.frame, 0); | ||
| 73 | } | ||
| 74 | } | ||
| 75 | TEST_CASE(simloop_render_not_retriggered_capped_initial_frame) { | ||
| 76 | simloop_render_not_retriggered(metadata, 10, true); | ||
| 77 | } | ||
| 78 | TEST_CASE(simloop_render_not_retriggered_unlimited_initial_frame) { | ||
| 79 | simloop_render_not_retriggered(metadata, 0, true); | ||
| 80 | } | ||
| 81 | TEST_CASE(simloop_render_not_retriggered_capped_subsequent_frame) { | ||
| 82 | simloop_render_not_retriggered(metadata, 10, false); | ||
| 83 | } | ||
| 84 | TEST_CASE(simloop_render_not_retriggered_unlimited_subsequent_frame) { | ||
| 85 | simloop_render_not_retriggered(metadata, 0, false); | ||
| 86 | } | 59 | } |
| 87 | 60 | ||
| 88 | /// A simulation loop with no render frame cap: | 61 | /// A simulation loop with no render frame cap: |
| 89 | /// 1. Updates based on the desired update frame rate. | 62 | /// 1. Updates based on the desired update frame rate. |
| 90 | /// 2. Renders at every step. | 63 | /// 2. Does not throttle rendering. |
| 91 | TEST_CASE(simloop_no_render_frame_cap) { | 64 | TEST_CASE(simloop_no_render_frame_cap) { |
| 92 | constexpr int UPDATE_FPS = 10; // 100ms delta | 65 | constexpr int UPDATE_FPS = 10; // 100ms delta |
| 93 | const simloop_time_t UPDATE_DDT = | 66 | const simloop_time_t UPDATE_DDT = |
| @@ -104,19 +77,19 @@ TEST_CASE(simloop_no_render_frame_cap) { | |||
| 104 | 77 | ||
| 105 | simloop_update(&simloop, 0, &simout); | 78 | simloop_update(&simloop, 0, &simout); |
| 106 | TEST_TRUE(!simout.should_update); // Time has not advanced. | 79 | TEST_TRUE(!simout.should_update); // Time has not advanced. |
| 107 | TEST_TRUE(simout.should_render); // Initial render. | 80 | TEST_EQUAL(simout.throttle, 0); // No throttling with no render frame cap. |
| 108 | 81 | ||
| 109 | for (simloop_time_t t = STEP; t <= SIM_DURATION_SEC; t += STEP) { | 82 | for (simloop_time_t t = STEP; t <= SIM_DURATION_SEC; t += STEP) { |
| 110 | simloop_update(&simloop, STEP, &simout); | 83 | simloop_update(&simloop, STEP, &simout); |
| 111 | const bool expect_update = (t % UPDATE_DDT) == 0; | 84 | const bool expect_update = (t % UPDATE_DDT) == 0; |
| 112 | TEST_EQUAL(simout.should_update, expect_update); | 85 | TEST_EQUAL(simout.should_update, expect_update); |
| 113 | TEST_TRUE(simout.should_render); // Always renders. | 86 | TEST_EQUAL(simout.throttle, 0); |
| 114 | } | 87 | } |
| 115 | } | 88 | } |
| 116 | 89 | ||
| 117 | /// A simulation loop with a render frame cap: | 90 | /// A simulation loop with a render frame cap: |
| 118 | /// 1. Updates based on the desired update frame rate. | 91 | /// 1. Updates based on the desired update frame rate. |
| 119 | /// 2. Renders based on the desired render frame rate. | 92 | /// 2. Throttles rendering based on the desired render frame rate. |
| 120 | TEST_CASE(simloop_with_render_frame_cap) { | 93 | TEST_CASE(simloop_with_render_frame_cap) { |
| 121 | constexpr int UPDATE_FPS = 10; // 100ms delta | 94 | constexpr int UPDATE_FPS = 10; // 100ms delta |
| 122 | constexpr int RENDER_FPS = 5; // 200ms delta | 95 | constexpr int RENDER_FPS = 5; // 200ms delta |
| @@ -130,7 +103,6 @@ TEST_CASE(simloop_with_render_frame_cap) { | |||
| 130 | // We need simulation time to be an exact multiple of the desired deltas for | 103 | // We need simulation time to be an exact multiple of the desired deltas for |
| 131 | // the modulo comparisons below. | 104 | // the modulo comparisons below. |
| 132 | TEST_TRUE((UPDATE_DDT % STEP) == 0); | 105 | TEST_TRUE((UPDATE_DDT % STEP) == 0); |
| 133 | TEST_TRUE((RENDER_DDT % STEP) == 0); | ||
| 134 | 106 | ||
| 135 | Simloop simloop = simloop_make( | 107 | Simloop simloop = simloop_make( |
| 136 | &(SimloopArgs){.update_fps = UPDATE_FPS, .max_render_fps = RENDER_FPS}); | 108 | &(SimloopArgs){.update_fps = UPDATE_FPS, .max_render_fps = RENDER_FPS}); |
| @@ -138,13 +110,12 @@ TEST_CASE(simloop_with_render_frame_cap) { | |||
| 138 | 110 | ||
| 139 | simloop_update(&simloop, 0, &simout); | 111 | simloop_update(&simloop, 0, &simout); |
| 140 | TEST_TRUE(!simout.should_update); // Time has not advanced. | 112 | TEST_TRUE(!simout.should_update); // Time has not advanced. |
| 141 | TEST_TRUE(simout.should_render); // Initial render. | 113 | TEST_EQUAL(simout.throttle, 0); // No throttle since time has not advanced. |
| 142 | 114 | ||
| 143 | for (simloop_time_t t = STEP; t <= SIM_DURATION_SEC; t += STEP) { | 115 | for (simloop_time_t t = STEP; t <= SIM_DURATION_SEC; t += STEP) { |
| 144 | simloop_update(&simloop, STEP, &simout); | 116 | simloop_update(&simloop, STEP, &simout); |
| 145 | // A render is still expected at time 0. | ||
| 146 | TEST_EQUAL(simout.should_render, (t % RENDER_DDT) == 0); | ||
| 147 | TEST_EQUAL(simout.should_update, (t % UPDATE_DDT) == 0); | 117 | TEST_EQUAL(simout.should_update, (t % UPDATE_DDT) == 0); |
| 118 | TEST_NOTEQUAL(simout.throttle, 0); | ||
| 148 | } | 119 | } |
| 149 | } | 120 | } |
| 150 | 121 | ||
| @@ -166,12 +137,12 @@ TEST_CASE(simloop_percent_frame_01_large_jump) { | |||
| 166 | 137 | ||
| 167 | simloop_update(&simloop, 0, &simout); | 138 | simloop_update(&simloop, 0, &simout); |
| 168 | TEST_TRUE(!simout.should_update); // Time has not advanced. | 139 | TEST_TRUE(!simout.should_update); // Time has not advanced. |
| 169 | TEST_TRUE(simout.should_render); // Initial render. | ||
| 170 | 140 | ||
| 171 | for (simloop_time_t t = STEP; t <= SIM_DURATION_SEC; t += STEP) { | 141 | for (simloop_time_t t = STEP; t <= SIM_DURATION_SEC; t += STEP) { |
| 172 | simloop_update(&simloop, STEP, &simout); | 142 | simloop_update(&simloop, STEP, &simout); |
| 173 | TEST_TRUE(simout.should_update); // Tries to catch up to clock. | 143 | TEST_TRUE(simout.should_update); // Tries to catch up to clock. |
| 174 | TEST_TRUE(simout.should_render); | 144 | TEST_TRUE(0. <= simout.percent_frame); |
| 145 | TEST_TRUE(simout.percent_frame <= 1.); | ||
| 175 | } | 146 | } |
| 176 | } | 147 | } |
| 177 | 148 | ||
