aboutsummaryrefslogtreecommitdiff
path: root/simloop/test
diff options
context:
space:
mode:
Diffstat (limited to 'simloop/test')
-rw-r--r--simloop/test/simloop_test.c69
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).
35TEST_CASE(simloop_initial_render) { 33TEST_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. 45TEST_CASE(simloop_render_not_retriggered) {
49void 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}
75TEST_CASE(simloop_render_not_retriggered_capped_initial_frame) {
76 simloop_render_not_retriggered(metadata, 10, true);
77}
78TEST_CASE(simloop_render_not_retriggered_unlimited_initial_frame) {
79 simloop_render_not_retriggered(metadata, 0, true);
80}
81TEST_CASE(simloop_render_not_retriggered_capped_subsequent_frame) {
82 simloop_render_not_retriggered(metadata, 10, false);
83}
84TEST_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.
91TEST_CASE(simloop_no_render_frame_cap) { 64TEST_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.
120TEST_CASE(simloop_with_render_frame_cap) { 93TEST_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