From dab48eddde4069f6f30b23fb24c168f2d7358e3c Mon Sep 17 00:00:00 2001 From: Susko3 Date: Sat, 28 Jun 2025 18:57:35 +0200 Subject: [PATCH] Add tests for checking equivalency of SDL_GetPerformanceCounter() and Stopwatch.GetTimestamp() --- SDL3-CS.Tests/TestTimestampSource.cs | 122 +++++++++++++++++++++++++++ 1 file changed, 122 insertions(+) create mode 100644 SDL3-CS.Tests/TestTimestampSource.cs diff --git a/SDL3-CS.Tests/TestTimestampSource.cs b/SDL3-CS.Tests/TestTimestampSource.cs new file mode 100644 index 0000000..814db9b --- /dev/null +++ b/SDL3-CS.Tests/TestTimestampSource.cs @@ -0,0 +1,122 @@ +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. + +using System.Diagnostics; +using NUnit.Framework; + +namespace SDL.Tests +{ + /// + /// These tests check that and use the same source of time. + /// + /// + /// You also need to check that the clocks remain consistent even after the system is put to sleep. To do so: + /// + /// Run both tests normally. + /// Run the tests one at a time, putting your computer to sleep while the test is running. + /// Adjust and as needed. + /// Run both tests normally. (Checks consistency after a sleep cycle.) + /// + /// + public class TestTimestampSource + { + public const int ITERATIONS = 5; + public const int SLEEP_TIMEOUT = 200; + + [OneTimeSetUp] + public void OneTimeSetUp() + { + SDL3.SDL_Init(0); + } + + [OneTimeTearDown] + public void OneTimeTearDown() + { + SDL3.SDL_Quit(); + } + + [Test] + public void TestSDLBoundedByStopwatch() + { + Assert.That(SDL3.SDL_GetPerformanceFrequency(), Is.EqualTo(Stopwatch.Frequency)); + + DateTime? wallClockLastEnd = null; + long? lastEnd = null; + + for (int i = 0; i < ITERATIONS; i++) + { + var wallClockStart = DateTime.UtcNow; + + long stopwatchStart = Stopwatch.GetTimestamp(); + ulong sdlTimestamp = SDL3.SDL_GetPerformanceCounter(); + long stopwatchEnd = Stopwatch.GetTimestamp(); + + var wallClockEnd = DateTime.UtcNow; + + Assert.That(sdlTimestamp, Is.GreaterThanOrEqualTo(stopwatchStart).And.LessThanOrEqualTo(stopwatchEnd)); + + if (lastEnd.HasValue && wallClockLastEnd.HasValue) + { + long diff = stopwatchStart - lastEnd.Value; + double seconds = (double)diff / Stopwatch.Frequency; + double wallClockSeconds = (wallClockStart - wallClockLastEnd.Value).TotalSeconds; + Console.WriteLine($"Elapsed inter-iteration: {diff} ({seconds} s), wall clock: {wallClockSeconds} s"); + Console.WriteLine(); + } + + Console.WriteLine($"Stw: {stopwatchStart}"); + Console.WriteLine($"SDL: {sdlTimestamp}"); + Console.WriteLine($"Stw: {stopwatchEnd}"); + Console.WriteLine($"Elapsed this interation: {stopwatchEnd - stopwatchStart}"); + Console.WriteLine(); + + lastEnd = stopwatchEnd; + wallClockLastEnd = wallClockEnd; + + Thread.Sleep(SLEEP_TIMEOUT); + } + } + + [Test] + public void TestStopwatchBoundedBySDL() + { + Assert.That(Stopwatch.Frequency, Is.EqualTo(SDL3.SDL_GetPerformanceFrequency())); + + DateTime? wallClockLastEnd = null; + ulong? lastEnd = null; + + for (int i = 0; i < ITERATIONS; i++) + { + var wallClockStart = DateTime.UtcNow; + + ulong sdlStart = SDL3.SDL_GetPerformanceCounter(); + long stopwatchTimestamp = Stopwatch.GetTimestamp(); + ulong sdlEnd = SDL3.SDL_GetPerformanceCounter(); + + var wallClockEnd = DateTime.UtcNow; + + Assert.That(stopwatchTimestamp, Is.GreaterThanOrEqualTo(sdlStart).And.LessThanOrEqualTo(sdlEnd)); + + if (lastEnd.HasValue && wallClockLastEnd.HasValue) + { + ulong diff = sdlStart - lastEnd.Value; + double seconds = (double)diff / SDL3.SDL_GetPerformanceFrequency(); + double wallClockSeconds = (wallClockStart - wallClockLastEnd.Value).TotalSeconds; + Console.WriteLine($"Elapsed inter-iteration: {diff} ({seconds} s), wall clock: {wallClockSeconds} s"); + Console.WriteLine(); + } + + Console.WriteLine($"SDL: {sdlStart}"); + Console.WriteLine($"Stw: {stopwatchTimestamp}"); + Console.WriteLine($"SDL: {sdlEnd}"); + Console.WriteLine($"Elapsed: {sdlEnd - sdlStart}"); + Console.WriteLine(); + + lastEnd = sdlEnd; + wallClockLastEnd = wallClockEnd; + + Thread.Sleep(SLEEP_TIMEOUT); + } + } + } +}