summaryrefslogtreecommitdiff
path: root/src/contrib/SDL-3.2.20/test/testtimer.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/contrib/SDL-3.2.20/test/testtimer.c')
-rw-r--r--src/contrib/SDL-3.2.20/test/testtimer.c287
1 files changed, 287 insertions, 0 deletions
diff --git a/src/contrib/SDL-3.2.20/test/testtimer.c b/src/contrib/SDL-3.2.20/test/testtimer.c
new file mode 100644
index 0000000..0f12dce
--- /dev/null
+++ b/src/contrib/SDL-3.2.20/test/testtimer.c
@@ -0,0 +1,287 @@
1/*
2 Copyright (C) 1997-2025 Sam Lantinga <slouken@libsdl.org>
3
4 This software is provided 'as-is', without any express or implied
5 warranty. In no event will the authors be held liable for any damages
6 arising from the use of this software.
7
8 Permission is granted to anyone to use this software for any purpose,
9 including commercial applications, and to alter it and redistribute it
10 freely.
11*/
12
13/* Test program to check the resolution of the SDL timer on the current
14 platform
15*/
16#include <SDL3/SDL.h>
17#include <SDL3/SDL_main.h>
18#include <SDL3/SDL_test.h>
19
20#define DEFAULT_RESOLUTION 1
21
22static int test_sdl_delay_within_bounds(void) {
23 const int testDelay = 100;
24 const int marginOfError = 25;
25 Uint64 result;
26 Uint64 result2;
27 Sint64 difference;
28
29 SDLTest_ResetAssertSummary();
30
31 /* Get ticks count - should be non-zero by now */
32 result = SDL_GetTicks();
33 SDLTest_AssertPass("Call to SDL_GetTicks()");
34 SDLTest_AssertCheck(result > 0, "Check result value, expected: >0, got: %" SDL_PRIu64, result);
35
36 /* Delay a bit longer and measure ticks and verify difference */
37 SDL_Delay(testDelay);
38 SDLTest_AssertPass("Call to SDL_Delay(%d)", testDelay);
39 result2 = SDL_GetTicks();
40 SDLTest_AssertPass("Call to SDL_GetTicks()");
41 SDLTest_AssertCheck(result2 > 0, "Check result value, expected: >0, got: %" SDL_PRIu64, result2);
42 difference = result2 - result;
43 SDLTest_AssertCheck(difference > (testDelay - marginOfError), "Check difference, expected: >%d, got: %" SDL_PRIu64, testDelay - marginOfError, difference);
44 /* Disabled because this might fail on non-interactive systems. */
45 SDLTest_AssertCheck(difference < (testDelay + marginOfError), "Check difference, expected: <%d, got: %" SDL_PRIu64, testDelay + marginOfError, difference);
46
47 return SDLTest_AssertSummaryToTestResult() == TEST_RESULT_PASSED ? 0 : 1;
48}
49
50static int ticks = 0;
51
52static Uint32 SDLCALL
53ticktock(void *param, SDL_TimerID timerID, Uint32 interval)
54{
55 ++ticks;
56 return interval;
57}
58
59static Uint64 SDLCALL
60ticktockNS(void *param, SDL_TimerID timerID, Uint64 interval)
61{
62 ++ticks;
63 return interval;
64}
65
66static Uint32 SDLCALL
67callback(void *param, SDL_TimerID timerID, Uint32 interval)
68{
69 int value = (int)(uintptr_t)param;
70 SDL_assert( value == 1 || value == 2 || value == 3 );
71 SDL_Log("Timer %" SDL_PRIu32 " : param = %d", interval, value);
72 return interval;
73}
74
75int main(int argc, char *argv[])
76{
77 int i;
78 int desired = -1;
79 SDL_TimerID t1, t2, t3;
80 Uint64 start, now;
81 Uint64 start_perf, now_perf;
82 SDLTest_CommonState *state;
83 bool run_interactive_tests = true;
84 int return_code = 0;
85
86 /* Initialize test framework */
87 state = SDLTest_CommonCreateState(argv, 0);
88 if (!state) {
89 return 1;
90 }
91
92 /* Parse commandline */
93 for (i = 1; i < argc;) {
94 int consumed;
95
96 consumed = SDLTest_CommonArg(state, i);
97 if (!consumed) {
98 if (SDL_strcmp(argv[i], "--no-interactive") == 0) {
99 run_interactive_tests = false;
100 consumed = 1;
101 } else if (desired < 0) {
102 char *endptr;
103
104 desired = SDL_strtoul(argv[i], &endptr, 0);
105 if (desired != 0 && endptr != argv[i] && *endptr == '\0') {
106 consumed = 1;
107 }
108 }
109 }
110 if (consumed <= 0) {
111 static const char *options[] = { "[--no-interactive]", "[interval]", NULL };
112 SDLTest_CommonLogUsage(state, argv[0], options);
113 return 1;
114 }
115
116 i += consumed;
117 }
118
119 if (SDL_GetEnvironmentVariable(SDL_GetEnvironment(), "SDL_TESTS_QUICK") != NULL) {
120 SDL_Log("Not running slower tests");
121 SDL_Quit();
122 return 0;
123 }
124
125 /* Verify SDL_GetTicks* acts monotonically increasing, and not erratic. */
126 SDL_Log("Sanity-checking GetTicks");
127 for (i = 0; i < 1000; ++i) {
128 start = SDL_GetTicks();
129 SDL_Delay(1);
130 now = SDL_GetTicks() - start;
131 if (now > 100) {
132 SDL_LogError(SDL_LOG_CATEGORY_APPLICATION, "testtimer.c: Delta time erratic at iter %d. Delay 1ms = %d ms in ticks", i, (int)now);
133 SDL_Quit();
134 return 1;
135 }
136 }
137
138 /* Start the millisecond timer */
139 if (desired < 0) {
140 desired = DEFAULT_RESOLUTION;
141 }
142 ticks = 0;
143 t1 = SDL_AddTimer(desired, ticktock, NULL);
144
145 /* Wait 1 seconds */
146 SDL_Log("Waiting 1 seconds for millisecond timer");
147 SDL_Delay(1 * 1000);
148
149 /* Stop the timer */
150 SDL_RemoveTimer(t1);
151
152 /* Print the results */
153 if (ticks) {
154 SDL_Log("Millisecond timer resolution: desired = %d ms, actual = %f ms",
155 desired, (double)(10 * 1000) / ticks);
156 }
157
158 /* Wait for the results to be seen */
159 SDL_Delay(1 * 1000);
160
161 /* Start the nanosecond timer */
162 ticks = 0;
163 t1 = SDL_AddTimerNS(desired, ticktockNS, NULL);
164
165 /* Wait 1 seconds */
166 SDL_Log("Waiting 1 seconds for nanosecond timer");
167 SDL_Delay(1 * 1000);
168
169 /* Stop the timer */
170 SDL_RemoveTimer(t1);
171
172 /* Print the results */
173 if (ticks) {
174 SDL_Log("Nanosecond timer resolution: desired = %d ns, actual = %f ns",
175 desired, (double)(10 * 1000000) / ticks);
176 }
177
178 /* Wait for the results to be seen */
179 SDL_Delay(1 * 1000);
180
181 /* Check accuracy of nanosecond delay */
182 {
183 Uint64 desired_delay = SDL_NS_PER_SECOND / 60;
184 Uint64 actual_delay;
185 Uint64 total_overslept = 0;
186
187 start = SDL_GetTicksNS();
188 SDL_DelayNS(1);
189 now = SDL_GetTicksNS();
190 actual_delay = (now - start);
191 SDL_Log("Minimum nanosecond delay: %" SDL_PRIu64 " ns", actual_delay);
192
193 SDL_Log("Timing 100 frames at 60 FPS");
194 for (i = 0; i < 100; ++i) {
195 start = SDL_GetTicksNS();
196 SDL_DelayNS(desired_delay);
197 now = SDL_GetTicksNS();
198 actual_delay = (now - start);
199 if (actual_delay > desired_delay) {
200 total_overslept += (actual_delay - desired_delay);
201 }
202 }
203 SDL_Log("Overslept %.2f ms", (double)total_overslept / SDL_NS_PER_MS);
204 }
205
206 /* Wait for the results to be seen */
207 SDL_Delay(1 * 1000);
208
209 /* Check accuracy of precise delay */
210 {
211 Uint64 desired_delay = SDL_NS_PER_SECOND / 60;
212 Uint64 actual_delay;
213 Uint64 total_overslept = 0;
214
215 start = SDL_GetTicksNS();
216 SDL_DelayPrecise(1);
217 now = SDL_GetTicksNS();
218 actual_delay = (now - start);
219 SDL_Log("Minimum precise delay: %" SDL_PRIu64 " ns", actual_delay);
220
221 SDL_Log("Timing 100 frames at 60 FPS");
222 for (i = 0; i < 100; ++i) {
223 start = SDL_GetTicksNS();
224 SDL_DelayPrecise(desired_delay);
225 now = SDL_GetTicksNS();
226 actual_delay = (now - start);
227 if (actual_delay > desired_delay) {
228 total_overslept += (actual_delay - desired_delay);
229 }
230 }
231 SDL_Log("Overslept %.2f ms", (double)total_overslept / SDL_NS_PER_MS);
232 }
233
234 /* Wait for the results to be seen */
235 SDL_Delay(1 * 1000);
236
237 /* Test multiple timers */
238 SDL_Log("Testing multiple timers...");
239 t1 = SDL_AddTimer(100, callback, (void *)1);
240 if (!t1) {
241 SDL_LogError(SDL_LOG_CATEGORY_APPLICATION, "Could not create timer 1: %s", SDL_GetError());
242 }
243 t2 = SDL_AddTimer(50, callback, (void *)2);
244 if (!t2) {
245 SDL_LogError(SDL_LOG_CATEGORY_APPLICATION, "Could not create timer 2: %s", SDL_GetError());
246 }
247 t3 = SDL_AddTimer(233, callback, (void *)3);
248 if (!t3) {
249 SDL_LogError(SDL_LOG_CATEGORY_APPLICATION, "Could not create timer 3: %s", SDL_GetError());
250 }
251
252 /* Wait 3 seconds */
253 SDL_Log("Waiting 3 seconds");
254 SDL_Delay(3 * 1000);
255
256 SDL_Log("Removing timer 1 and waiting 3 more seconds");
257 SDL_RemoveTimer(t1);
258
259 SDL_Delay(3 * 1000);
260
261 SDL_RemoveTimer(t2);
262 SDL_RemoveTimer(t3);
263
264 ticks = 0;
265 start_perf = SDL_GetPerformanceCounter();
266 for (i = 0; i < 1000000; ++i) {
267 ticktock(NULL, 0, 0);
268 }
269 now_perf = SDL_GetPerformanceCounter();
270 SDL_Log("1 million iterations of ticktock took %f ms", (double)((now_perf - start_perf) * 1000) / SDL_GetPerformanceFrequency());
271
272 SDL_Log("Performance counter frequency: %" SDL_PRIu64, SDL_GetPerformanceFrequency());
273 start = SDL_GetTicks();
274 start_perf = SDL_GetPerformanceCounter();
275 SDL_Delay(1000);
276 now_perf = SDL_GetPerformanceCounter();
277 now = SDL_GetTicks();
278 SDL_Log("Delay 1 second = %d ms in ticks, %f ms according to performance counter", (int)(now - start), (double)((now_perf - start_perf) * 1000) / SDL_GetPerformanceFrequency());
279
280 if (run_interactive_tests) {
281 return_code = test_sdl_delay_within_bounds();
282 }
283
284 SDL_Quit();
285 SDLTest_CommonDestroyState(state);
286 return return_code;
287}