sdl2-compat: sync tests with latest SDL2. (cc419)

From cc419053cfe97979279d5534b11fbe401e2e5fea Mon Sep 17 00:00:00 2001
From: Ozkan Sezer <[EMAIL REDACTED]>
Date: Tue, 23 Jan 2024 01:23:20 +0300
Subject: [PATCH] sync tests with latest SDL2.

---
 test/testautomation_audio.c    | 171 ++++++++++++++++---
 test/testautomation_events.c   |   4 +
 test/testautomation_keyboard.c |  22 +--
 test/testautomation_main.c     |  44 +----
 test/testautomation_math.c     | 296 +++++++++++++++------------------
 test/testautomation_timer.c    |   3 +
 test/testautomation_video.c    |   5 +
 test/testhaptic.c              |   2 +
 test/testtimer.c               |  76 ++++++++-
 9 files changed, 376 insertions(+), 247 deletions(-)

diff --git a/test/testautomation_audio.c b/test/testautomation_audio.c
index 03cc646..16ab753 100644
--- a/test/testautomation_audio.c
+++ b/test/testautomation_audio.c
@@ -52,6 +52,42 @@ void SDLCALL _audio_testCallback(void *userdata, Uint8 *stream, int len)
     _audio_testCallbackLength += len;
 }
 
+#if defined(__linux__)
+/* Linux builds can include many audio drivers, but some are very
+ * obscure and typically unsupported on modern systems. They will
+ * be skipped in tests that run against all included drivers, as
+ * they are basically guaranteed to fail.
+ */
+static SDL_bool DriverIsProblematic(const char *driver)
+{
+    static const char *driverList[] = {
+        /* Omnipresent in Linux builds, but deprecated since 2002,
+        * very rarely used on Linux nowadays, and is almost certainly
+        * guaranteed to fail.
+         */
+        "dsp",
+
+        /* OpenBSD sound API. Can be used on Linux, but very rare. */
+        "sndio",
+
+        /* Always fails on initialization and/or opening a device.
+         * Does anyone or anything actually use this?
+         */
+        "nas"
+    };
+
+    int i;
+
+    for (i = 0; i < SDL_arraysize(driverList); ++i) {
+        if (SDL_strcmp(driver, driverList[i]) == 0) {
+            return SDL_TRUE;
+        }
+    }
+
+    return SDL_FALSE;
+}
+#endif
+
 /* Test case functions */
 
 /**
@@ -89,15 +125,33 @@ int audio_initQuitAudio()
     SDL_QuitSubSystem(SDL_INIT_AUDIO);
     SDLTest_AssertPass("Call to SDL_QuitSubSystem(SDL_INIT_AUDIO)");
 
-    /* Loop over all available audio drivers */
-    iMax = SDL_GetNumAudioDrivers();
-    SDLTest_AssertPass("Call to SDL_GetNumAudioDrivers()");
-    SDLTest_AssertCheck(iMax > 0, "Validate number of audio drivers; expected: >0 got: %d", iMax);
+    /* Was a specific driver requested? */
+    audioDriver = SDL_GetHint(SDL_HINT_AUDIODRIVER);
+
+    if (audioDriver == NULL) {
+        /* Loop over all available audio drivers */
+        iMax = SDL_GetNumAudioDrivers();
+        SDLTest_AssertPass("Call to SDL_GetNumAudioDrivers()");
+        SDLTest_AssertCheck(iMax > 0, "Validate number of audio drivers; expected: >0 got: %d", iMax);
+    } else {
+        /* A specific driver was requested for testing */
+        iMax = 1;
+    }
     for (i = 0; i < iMax; i++) {
-        audioDriver = SDL_GetAudioDriver(i);
-        SDLTest_AssertPass("Call to SDL_GetAudioDriver(%d)", i);
-        SDLTest_Assert(audioDriver != NULL, "Audio driver name is not NULL");
-        SDLTest_AssertCheck(audioDriver[0] != '\0', "Audio driver name is not empty; got: %s", audioDriver); /* NOLINT(clang-analyzer-core.NullDereference): Checked for NULL above */
+        if (audioDriver == NULL) {
+            audioDriver = SDL_GetAudioDriver(i);
+            SDLTest_AssertPass("Call to SDL_GetAudioDriver(%d)", i);
+            SDLTest_Assert(audioDriver != NULL, "Audio driver name is not NULL");
+            SDLTest_AssertCheck(audioDriver[0] != '\0', "Audio driver name is not empty; got: %s", audioDriver); /* NOLINT(clang-analyzer-core.NullDereference): Checked for NULL above */
+
+#if defined(__linux__)
+            if (DriverIsProblematic(audioDriver)) {
+                SDLTest_Log("Audio driver '%s' flagged as problematic: skipping init/quit test (set SDL_AUDIODRIVER=%s to force)", audioDriver, audioDriver);
+                audioDriver = NULL;
+                continue;
+            }
+#endif
+        }
 
         if (hint && SDL_strcmp(audioDriver, hint) != 0) {
             continue;
@@ -111,6 +165,8 @@ int audio_initQuitAudio()
         /* Call Quit */
         SDL_AudioQuit();
         SDLTest_AssertPass("Call to SDL_AudioQuit()");
+
+        audioDriver = NULL;
     }
 
     /* NULL driver specification */
@@ -151,15 +207,33 @@ int audio_initOpenCloseQuitAudio()
     SDL_QuitSubSystem(SDL_INIT_AUDIO);
     SDLTest_AssertPass("Call to SDL_QuitSubSystem(SDL_INIT_AUDIO)");
 
-    /* Loop over all available audio drivers */
-    iMax = SDL_GetNumAudioDrivers();
-    SDLTest_AssertPass("Call to SDL_GetNumAudioDrivers()");
-    SDLTest_AssertCheck(iMax > 0, "Validate number of audio drivers; expected: >0 got: %d", iMax);
+    /* Was a specific driver requested? */
+    audioDriver = SDL_GetHint(SDL_HINT_AUDIODRIVER);
+
+    if (audioDriver == NULL) {
+        /* Loop over all available audio drivers */
+        iMax = SDL_GetNumAudioDrivers();
+        SDLTest_AssertPass("Call to SDL_GetNumAudioDrivers()");
+        SDLTest_AssertCheck(iMax > 0, "Validate number of audio drivers; expected: >0 got: %d", iMax);
+    } else {
+        /* A specific driver was requested for testing */
+        iMax = 1;
+    }
     for (i = 0; i < iMax; i++) {
-        audioDriver = SDL_GetAudioDriver(i);
-        SDLTest_AssertPass("Call to SDL_GetAudioDriver(%d)", i);
-        SDLTest_Assert(audioDriver != NULL, "Audio driver name is not NULL");
-        SDLTest_AssertCheck(audioDriver[0] != '\0', "Audio driver name is not empty; got: %s", audioDriver); /* NOLINT(clang-analyzer-core.NullDereference): Checked for NULL above */
+        if (audioDriver == NULL) {
+            audioDriver = SDL_GetAudioDriver(i);
+            SDLTest_AssertPass("Call to SDL_GetAudioDriver(%d)", i);
+            SDLTest_Assert(audioDriver != NULL, "Audio driver name is not NULL");
+            SDLTest_AssertCheck(audioDriver[0] != '\0', "Audio driver name is not empty; got: %s", audioDriver); /* NOLINT(clang-analyzer-core.NullDereference): Checked for NULL above */
+
+#if defined(__linux__)
+            if (DriverIsProblematic(audioDriver)) {
+                SDLTest_Log("Audio driver '%s' flagged as problematic: skipping device open/close test (set SDL_AUDIODRIVER=%s to force)", audioDriver, audioDriver);
+                audioDriver = NULL;
+                continue;
+            }
+#endif
+        }
 
         if (hint && SDL_strcmp(audioDriver, hint) != 0) {
             continue;
@@ -173,6 +247,17 @@ int audio_initOpenCloseQuitAudio()
             SDLTest_AssertPass("Call to SDL_AudioInit('%s')", audioDriver);
             SDLTest_AssertCheck(result == 0, "Validate result value; expected: 0 got: %d", result);
 
+            /* Check for output devices */
+            result = SDL_GetNumAudioDevices(SDL_FALSE);
+            SDLTest_AssertPass("Call to SDL_GetNumAudioDevices(SDL_FALSE)");
+            SDLTest_AssertCheck(result >= 0, "Validate result value; expected: >=0 got: %d", result);
+            if (result <= 0) {
+                SDLTest_Log("No output devices for '%s': skipping device open/close test", audioDriver);
+                SDL_AudioQuit();
+                SDLTest_AssertPass("Call to SDL_AudioQuit()");
+                break;
+            }
+
             /* Set spec */
             SDL_memset(&desired, 0, sizeof(desired));
             switch (j) {
@@ -217,7 +302,10 @@ int audio_initOpenCloseQuitAudio()
             }
 
         } /* spec loop */
-    }     /* driver loop */
+
+        audioDriver = NULL;
+
+    } /* driver loop */
 
     /* Restart audio again */
     _audioSetUp(NULL);
@@ -245,15 +333,33 @@ int audio_pauseUnpauseAudio()
     SDL_QuitSubSystem(SDL_INIT_AUDIO);
     SDLTest_AssertPass("Call to SDL_QuitSubSystem(SDL_INIT_AUDIO)");
 
-    /* Loop over all available audio drivers */
-    iMax = SDL_GetNumAudioDrivers();
-    SDLTest_AssertPass("Call to SDL_GetNumAudioDrivers()");
-    SDLTest_AssertCheck(iMax > 0, "Validate number of audio drivers; expected: >0 got: %d", iMax);
+    /* Was a specific driver requested? */
+    audioDriver = SDL_GetHint(SDL_HINT_AUDIODRIVER);
+
+    if (audioDriver == NULL) {
+        /* Loop over all available audio drivers */
+        iMax = SDL_GetNumAudioDrivers();
+        SDLTest_AssertPass("Call to SDL_GetNumAudioDrivers()");
+        SDLTest_AssertCheck(iMax > 0, "Validate number of audio drivers; expected: >0 got: %d", iMax);
+    } else {
+        /* A specific driver was requested for testing */
+        iMax = 1;
+    }
     for (i = 0; i < iMax; i++) {
-        audioDriver = SDL_GetAudioDriver(i);
-        SDLTest_AssertPass("Call to SDL_GetAudioDriver(%d)", i);
-        SDLTest_Assert(audioDriver != NULL, "Audio driver name is not NULL");
-        SDLTest_AssertCheck(audioDriver[0] != '\0', "Audio driver name is not empty; got: %s", audioDriver); /* NOLINT(clang-analyzer-core.NullDereference): Checked for NULL above */
+        if (audioDriver == NULL) {
+            audioDriver = SDL_GetAudioDriver(i);
+            SDLTest_AssertPass("Call to SDL_GetAudioDriver(%d)", i);
+            SDLTest_Assert(audioDriver != NULL, "Audio driver name is not NULL");
+            SDLTest_AssertCheck(audioDriver[0] != '\0', "Audio driver name is not empty; got: %s", audioDriver); /* NOLINT(clang-analyzer-core.NullDereference): Checked for NULL above */
+
+#if defined(__linux__)
+            if (DriverIsProblematic(audioDriver)) {
+                SDLTest_Log("Audio driver '%s' flagged as problematic: skipping pause/unpause test (set SDL_AUDIODRIVER=%s to force)", audioDriver, audioDriver);
+                audioDriver = NULL;
+                continue;
+            }
+#endif
+        }
 
         if (hint && SDL_strcmp(audioDriver, hint) != 0) {
             continue;
@@ -267,6 +373,16 @@ int audio_pauseUnpauseAudio()
             SDLTest_AssertPass("Call to SDL_AudioInit('%s')", audioDriver);
             SDLTest_AssertCheck(result == 0, "Validate result value; expected: 0 got: %d", result);
 
+            result = SDL_GetNumAudioDevices(SDL_FALSE);
+            SDLTest_AssertPass("Call to SDL_GetNumAudioDevices(SDL_FALSE)");
+            SDLTest_AssertCheck(result >= 0, "Validate result value; expected: >=0 got: %d", result);
+            if (result <= 0) {
+                SDLTest_Log("No output devices for '%s': skipping pause/unpause test", audioDriver);
+                SDL_AudioQuit();
+                SDLTest_AssertPass("Call to SDL_AudioQuit()");
+                break;
+            }
+
             /* Set spec */
             SDL_memset(&desired, 0, sizeof(desired));
             switch (j) {
@@ -341,7 +457,10 @@ int audio_pauseUnpauseAudio()
             SDLTest_AssertPass("Call to SDL_AudioQuit()");
 
         } /* spec loop */
-    }     /* driver loop */
+
+        audioDriver = NULL;
+
+    } /* driver loop */
 
     /* Restart audio again */
     _audioSetUp(NULL);
diff --git a/test/testautomation_events.c b/test/testautomation_events.c
index 6d0f3ff..d4babda 100644
--- a/test/testautomation_events.c
+++ b/test/testautomation_events.c
@@ -68,6 +68,10 @@ int events_pushPumpAndPollUserevent(void *arg)
     SDLTest_AssertPass("Call to SDL_PollEvent()");
     SDLTest_AssertCheck(result == 1, "Check result from SDL_PollEvent, expected: 1, got: %d", result);
 
+    /* Need to finish getting all events and sentinel, otherwise other tests that rely on event are in bad state */
+    while (SDL_PollEvent(&event2)) {
+    }
+
     return TEST_COMPLETED;
 }
 
diff --git a/test/testautomation_keyboard.c b/test/testautomation_keyboard.c
index 153a4a0..5ed9207 100644
--- a/test/testautomation_keyboard.c
+++ b/test/testautomation_keyboard.c
@@ -463,32 +463,34 @@ int keyboard_setTextInputRect(void *arg)
  */
 int keyboard_setTextInputRectNegative(void *arg)
 {
+    int platform_sets_error_message = SDL_strcmp(SDL_GetCurrentVideoDriver(), "windows") == 0 ||
+                                      SDL_strcmp(SDL_GetCurrentVideoDriver(), "android") == 0 ||
+                                      SDL_strcmp(SDL_GetCurrentVideoDriver(), "cococa") == 0;
     /* Some platforms set also an error message; prepare for checking it */
-#if defined(SDL_VIDEO_DRIVER_WINDOWS) || defined(SDL_VIDEO_DRIVER_ANDROID) || defined(SDL_VIDEO_DRIVER_COCOA)
     const char *expectedError = "Parameter 'rect' is invalid";
     const char *error;
 
     SDL_ClearError();
     SDLTest_AssertPass("Call to SDL_ClearError()");
-#endif
 
     /* NULL refRect */
     SDL_SetTextInputRect(NULL);
     SDLTest_AssertPass("Call to SDL_SetTextInputRect(NULL)");
 
     /* Some platforms set also an error message; so check it */
-#if defined(SDL_VIDEO_DRIVER_WINDOWS) || defined(SDL_VIDEO_DRIVER_ANDROID) || defined(SDL_VIDEO_DRIVER_COCOA)
-    error = SDL_GetError();
-    SDLTest_AssertPass("Call to SDL_GetError()");
-    SDLTest_AssertCheck(error != NULL, "Validate that error message was not NULL");
-    if (error != NULL) {
-        SDLTest_AssertCheck(SDL_strcmp(error, expectedError) == 0,
-                            "Validate error message, expected: '%s', got: '%s'", expectedError, error);
+
+    if (platform_sets_error_message) {
+        error = SDL_GetError();
+        SDLTest_AssertPass("Call to SDL_GetError()");
+        SDLTest_AssertCheck(error != NULL, "Validate that error message was not NULL");
+        if (error != NULL) {
+            SDLTest_AssertCheck(SDL_strcmp(error, expectedError) == 0,
+                                "Validate error message, expected: '%s', got: '%s'", expectedError, error);
+        }
     }
 
     SDL_ClearError();
     SDLTest_AssertPass("Call to SDL_ClearError()");
-#endif
 
     return TEST_COMPLETED;
 }
diff --git a/test/testautomation_main.c b/test/testautomation_main.c
index 1f5af93..78572d1 100644
--- a/test/testautomation_main.c
+++ b/test/testautomation_main.c
@@ -9,37 +9,6 @@
 #include "SDL.h"
 #include "SDL_test.h"
 
-/* !
- * \brief Tests SDL_Init() and SDL_Quit() of Joystick and Haptic subsystems
- * \sa
- * http://wiki.libsdl.org/SDL_Init
- * http://wiki.libsdl.org/SDL_Quit
- */
-static int main_testInitQuitJoystickHaptic(void *arg)
-{
-#if defined SDL_JOYSTICK_DISABLED || defined SDL_HAPTIC_DISABLED
-    return TEST_SKIPPED;
-#else
-    int enabled_subsystems;
-    int previous_subsystems = SDL_WasInit(SDL_INIT_EVERYTHING);
-    int initialized_subsystems = SDL_INIT_JOYSTICK | SDL_INIT_HAPTIC;
-
-    SDLTest_AssertCheck(SDL_Init(initialized_subsystems) == 0, "SDL_Init multiple systems.");
-
-    enabled_subsystems = SDL_WasInit(initialized_subsystems);
-    SDLTest_AssertCheck(enabled_subsystems == initialized_subsystems, "SDL_WasInit(SDL_INIT_EVERYTHING) contains all systems (%i)", enabled_subsystems);
-
-    SDL_Quit();
-
-    enabled_subsystems = SDL_WasInit(initialized_subsystems);
-    SDLTest_AssertCheck(enabled_subsystems == 0, "SDL_Quit should shut down everything (%i)", enabled_subsystems);
-
-    SDL_Init(previous_subsystems);
-
-    return TEST_COMPLETED;
-#endif
-}
-
 /* !
  * \brief Tests SDL_InitSubSystem() and SDL_QuitSubSystem()
  * \sa
@@ -157,22 +126,18 @@ main_testSetError(void *arg)
 #endif
 
 static const SDLTest_TestCaseReference mainTest1 = {
-    (SDLTest_TestCaseFp)main_testInitQuitJoystickHaptic, "main_testInitQuitJoystickHaptic", "Tests SDL_Init/Quit of Joystick and Haptic subsystem", TEST_ENABLED
-};
-
-static const SDLTest_TestCaseReference mainTest2 = {
     (SDLTest_TestCaseFp)main_testInitQuitSubSystem, "main_testInitQuitSubSystem", "Tests SDL_InitSubSystem/QuitSubSystem", TEST_ENABLED
 };
 
-static const SDLTest_TestCaseReference mainTest3 = {
+static const SDLTest_TestCaseReference mainTest2 = {
     (SDLTest_TestCaseFp)main_testImpliedJoystickInit, "main_testImpliedJoystickInit", "Tests that init for gamecontroller properly implies joystick", TEST_ENABLED
 };
 
-static const SDLTest_TestCaseReference mainTest4 = {
+static const SDLTest_TestCaseReference mainTest3 = {
     (SDLTest_TestCaseFp)main_testImpliedJoystickQuit, "main_testImpliedJoystickQuit", "Tests that quit for gamecontroller doesn't quit joystick if you inited it explicitly", TEST_ENABLED
 };
 
-static const SDLTest_TestCaseReference mainTest5 = {
+static const SDLTest_TestCaseReference mainTest4 = {
     (SDLTest_TestCaseFp)main_testSetError, "main_testSetError", "Tests that SDL_SetError() handles arbitrarily large strings", TEST_ENABLED
 };
 
@@ -182,7 +147,6 @@ static const SDLTest_TestCaseReference *mainTests[] = {
     &mainTest2,
     &mainTest3,
     &mainTest4,
-    &mainTest5,
     NULL
 };
 
@@ -193,5 +157,3 @@ SDLTest_TestSuiteReference mainTestSuite = {
     mainTests,
     NULL
 };
-
-/* vi: set ts=4 sw=4 expandtab: */
diff --git a/test/testautomation_math.c b/test/testautomation_math.c
index d8b53f6..ef9b40b 100644
--- a/test/testautomation_math.c
+++ b/test/testautomation_math.c
@@ -49,6 +49,12 @@ typedef struct
     double expected;
 } dd_to_d;
 
+#define DD_TO_D_CASE(IDX, X, Y, E) do { \
+        cases[IDX].x_input = (X);       \
+        cases[IDX].y_input = (Y);       \
+        cases[IDX].expected = (E);      \
+    } while (0)
+
 /*
     NB: You cannot create an array of these structures containing INFINITY or NAN.
     On platforms such as OS/2, they are defined as 'extern const double' making them
@@ -102,8 +108,15 @@ helper_dtod_inexact(const char *func_name, d_to_d_func func,
     Uint32 i;
     for (i = 0; i < cases_size; i++) {
         const double result = func(cases[i].input);
-        SDLTest_AssertCheck(result >= cases[i].expected - EPSILON &&
-                                result <= cases[i].expected + EPSILON,
+        double diff = result - cases[i].expected;
+        double max_err = (cases[i].expected + 1.) * EPSILON;
+        if (diff < 0) {
+            diff = -diff;
+        }
+        if (max_err < 0) {
+            max_err = -max_err;
+        }
+        SDLTest_AssertCheck(diff <= max_err,
                             "%s(%f), expected [%f,%f], got %f",
                             func_name,
                             cases[i].input,
@@ -131,6 +144,8 @@ helper_ddtod(const char *func_name, dd_to_d_func func,
     Uint32 i;
     for (i = 0; i < cases_size; i++) {
         const double result = func(cases[i].x_input, cases[i].y_input);
+        /* By using the result as input, the compiler is less likely to use higher precision floating point number */
+        (void)SDL_sin(result);
         SDLTest_AssertCheck(result == cases[i].expected,
                             "%s(%f,%f), expected %f, got %f",
                             func_name,
@@ -157,8 +172,16 @@ helper_ddtod_inexact(const char *func_name, dd_to_d_func func,
     Uint32 i;
     for (i = 0; i < cases_size; i++) {
         const double result = func(cases[i].x_input, cases[i].y_input);
-        SDLTest_AssertCheck(result >= cases[i].expected - EPSILON &&
-                                result <= cases[i].expected + EPSILON,
+        double diff = result - cases[i].expected;
+        double max_err = (cases[i].expected + 1.) * EPSILON;
+        if (diff < 0) {
+            diff = -diff;
+        }
+        if (max_err < 0) {
+            max_err = -max_err;
+        }
+
+        SDLTest_AssertCheck(diff <= max_err,
                             "%s(%f,%f), expected [%f,%f], got %f",
                             func_name,
                             cases[i].x_input, cases[i].y_input,
@@ -1655,7 +1678,7 @@ pow_regularCases(void *args)
         { 39.23, -1.5, 0.0040697950366865498147972424192175822099670767784118652343750 },
         { 478.972, 12.125, 315326359630449587856007411793920.0 }
     };
-    return helper_ddtod("Pow", SDL_pow, regular_cases, SDL_arraysize(regular_cases));
+    return helper_ddtod_inexact("Pow", SDL_pow, regular_cases, SDL_arraysize(regular_cases));
 }
 
 /**
@@ -1983,24 +2006,24 @@ static int
 cos_precisionTest(void *args)
 {
     const d_to_d precision_cases[] = {
-        { M_PI * 1.0 / 10.0, 0.9510565162 },
-        { M_PI * 2.0 / 10.0, 0.8090169943 },
-        { M_PI * 3.0 / 10.0, 0.5877852522 },
-        { M_PI * 4.0 / 10.0, 0.3090169943 },
+        { M_PI * 1.0 / 10.0, 0.9510565162951535 },
+        { M_PI * 2.0 / 10.0, 0.8090169943749475 },
+        { M_PI * 3.0 / 10.0, 0.5877852522924731 },
+        { M_PI * 4.0 / 10.0, 0.30901699437494745 },
         { M_PI * 5.0 / 10.0, 0.0 },
-        { M_PI * 6.0 / 10.0, -0.3090169943 },
-        { M_PI * 7.0 / 10.0, -0.5877852522 },
-        { M_PI * 8.0 / 10.0, -0.8090169943 },
-        { M_PI * 9.0 / 10.0, -0.9510565162 },
-        { M_PI * -1.0 / 10.0, 0.9510565162 },
-        { M_PI * -2.0 / 10.0, 0.8090169943 },
-        { M_PI * -3.0 / 10.0, 0.5877852522 },
-        { M_PI * -4.0 / 10.0, 0.3090169943 },
+        { M_PI * 6.0 / 10.0, -0.30901699437494734 },
+        { M_PI * 7.0 / 10.0, -0.587785252292473 },
+        { M_PI * 8.0 / 10.0, -0.8090169943749473 },
+        { M_PI * 9.0 / 10.0, -0.9510565162951535 },
+        { M_PI * -1.0 / 10.0, 0.9510565162951535 },
+        { M_PI * -2.0 / 10.0, 0.8090169943749475 },
+        { M_PI * -3.0 / 10.0, 0.5877852522924731 },
+        { M_PI * -4.0 / 10.0, 0.30901699437494745 },
         { M_PI * -5.0 / 10.0, 0.0 },
-        { M_PI * -6.0 / 10.0, -0.3090169943 },
-        { M_PI * -7.0 / 10.0, -0.5877852522 },
-        { M_PI * -8.0 / 10.0, -0.8090169943 },
-        { M_PI * -9.0 / 10.0, -0.9510565162 }
+        { M_PI * -6.0 / 10.0, -0.30901699437494734 },
+        { M_PI * -7.0 / 10.0, -0.587785252292473 },
+        { M_PI * -8.0 / 10.0, -0.8090169943749473 },
+        { M_PI * -9.0 / 10.0, -0.9510565162951535 }
     };
     return helper_dtod_inexact("Cos", SDL_cos, precision_cases, SDL_arraysize(precision_cases));
 }
@@ -2101,23 +2124,23 @@ static int
 sin_precisionTest(void *args)
 {
     const d_to_d precision_cases[] = {
-        { M_PI * 1.0 / 10.0, 0.3090169943 },
-        { M_PI * 2.0 / 10.0, 0.5877852522 },
-        { M_PI * 3.0 / 10.0, 0.8090169943 },
-        { M_PI * 4.0 / 10.0, 0.9510565162 },
-        { M_PI * 6.0 / 10.0, 0.9510565162 },
-        { M_PI * 7.0 / 10.0, 0.8090169943 },
-        { M_PI * 8.0 / 10.0, 0.5877852522 },
-        { M_PI * 9.0 / 10.0, 0.3090169943 },
+        { M_PI * 1.0 / 10.0, 0.3090169943749474 },
+        { M_PI * 2.0 / 10.0, 0.5877852522924731 },
+        { M_PI * 3.0 / 10.0, 0.8090169943749475 },
+        { M_PI * 4.0 / 10.0, 0.9510565162951535 },
+        { M_PI * 6.0 / 10.0, 0.9510565162951536 },
+        { M_PI * 7.0 / 10.0, 0.8090169943749475 },
+        { M_PI * 8.0 / 10.0, 0.5877852522924732 },
+        { M_PI * 9.0 / 10.0, 0.3090169943749475 },
         { M_PI, 0.0 },
-        { M_PI * -1.0 / 10.0, -0.3090169943 },
-        { M_PI * -2.0 / 10.0, -0.5877852522 },
-        { M_PI * -3.0 / 10.0, -0.8090169943 },
-        { M_PI * -4.0 / 10.0, -0.9510565162 },
-        { M_PI * -6.0 / 10.0, -0.9510565162 },
-        { M_PI * -7.0 / 10.0, -0.8090169943 },
-        { M_PI * -8.0 / 10.0, -0.5877852522 },
-        { M_PI * -9.0 / 10.0, -0.3090169943 },
+        { M_PI * -1.0 / 10.0, -0.3090169943749474 },
+        { M_PI * -2.0 / 10.0, -0.5877852522924731 },
+        { M_PI * -3.0 / 10.0, -0.8090169943749475 },
+        { M_PI * -4.0 / 10.0, -0.9510565162951535 },
+        { M_PI * -6.0 / 10.0, -0.9510565162951536 },
+        { M_PI * -7.0 / 10.0, -0.8090169943749475 },
+        { M_PI * -8.0 / 10.0, -0.5877852522924732 },
+        { M_PI * -9.0 / 10.0, -0.3090169943749475 },
         { -M_PI, 0.0 },
     };
     return helper_dtod_inexact("Sin", SDL_sin, precision_cases, SDL_arraysize(precision_cases));
@@ -2217,26 +2240,26 @@ static int
 tan_precisionTest(void *args)
 {
     const d_to_d precision_cases[] = {
-        { M_PI * 1.0 / 11.0, 0.2936264929 },
-        { M_PI * 2.0 / 11.0, 0.6426609771 },
-        { M_PI * 3.0 / 11.0, 1.1540615205 },
-        { M_PI * 4.0 / 11.0, 2.1896945629 },
-        { M_PI * 5.0 / 11.0, 6.9551527717 },
-        { M_PI * 6.0 / 11.0, -6.9551527717 },
-        { M_PI * 7.0 / 11.0, -2.1896945629 },
-        { M_PI * 8.0 / 11.0, -1.1540615205 },
-        { M_PI * 9.0 / 11.0, -0.6426609771 },
-        { M_PI * 10.0 / 11.0, -0.2936264929 },
-        { M_PI * -1.0 / 11.0, -0.2936264929 },
-        { M_PI * -2.0 / 11.0, -0.6426609771 },
-        { M_PI * -3.0 / 11.0, -1.1540615205 },
-        { M_PI * -4.0 / 11.0, -2.1896945629 },
-        { M_PI * -5.0 / 11.0, -6.9551527717 },
-        { M_PI * -6.0 / 11.0, 6.9551527717 },
-        { M_PI * -7.0 / 11.0, 2.1896945629 },
-        { M_PI * -8.0 / 11.0, 1.1540615205 },
-        { M_PI * -9.0 / 11.0, 0.6426609771 },
-        { M_PI * -10.0 / 11.0, 0.2936264929 }
+        { M_PI * 1.0 / 11.0, 0.29362649293836673 },
+        { M_PI * 2.0 / 11.0, 0.642660977168331 },
+        { M_PI * 3.0 / 11.0, 1.1540615205330094 },
+        { M_PI * 4.0 / 11.0, 2.189694562989681 },
+        { M_PI * 5.0 / 11.0, 6.9551527717734745 },
+        { M_PI * 6.0 / 11.0, -6.955152771773481 },
+        { M_PI * 7.0 / 11.0, -2.189694562989682 },
+        { M_PI * 8.0 / 11.0, -1.1540615205330096 },
+        { M_PI * 9.0 / 11.0, -0.6426609771683314 },
+        { M_PI * 10.0 / 11.0, -0.2936264929383667 },
+        { M_PI * -1.0 / 11.0, -0.29362649293836673 },
+        { M_PI * -2.0 / 11.0, -0.642660977168331 },
+        { M_PI * -3.0 / 11.0, -1.1540615205330094 },
+        { M_PI * -4.0 / 11.0, -2.189694562989681 },
+        { M_PI * -5.0 / 11.0, -6.9551527717734745 },
+        { M_PI * -6.0 / 11.0, 6.955152771773481 },
+        { M_PI * -7.0 / 11.0, 2.189694562989682 },
+        { M_PI * -8.0 / 11.0, 1.1540615205330096 },
+        { M_PI * -9.0 / 11.0, 0.6426609771683314 },
+        { M_PI * -10.0 / 11.0, 0.2936264929383667 }
     };
     return helper_dtod_inexact("Tan", SDL_tan, precision_cases, SDL_arraysize(precision_cases));
 }
@@ -2401,26 +2424,26 @@ static int
 asin_precisionTest(void *args)
 {
     const d_to_d precision_cases[] = {
-        { 0.9, 1.1197695149 },
-        { 0.8, 0.9272952180 },
-        { 0.7, 0.7753974966 },
-        { 0.6, 0.6435011087 },
-        { 0.5, 0.5235987755 },
-        { 0.4, 0.4115168460 },
-        { 0.3, 0.3046926540 },
-        { 0.2, 0.2013579207 },
-        { 0.1, 0.1001674211 },
+        { 0.9, 1.1197695149986342 },
+        { 0.8, 0.9272952180016123 },
+        { 0.7, 0.775397496610753 },
+        { 0.6, 0.6435011087932844 },
+        { 0.5, 0.5235987755982989 },
+        { 0.4, 0.41151684606748806 },
+        { 0.3, 0.3046926540153976 },
+        { 0.2, 0.20135792079033074 },
+        { 0.1, 0.10016742116155977 },
         { 0.0, 0.0 },
         { -0.0, -0.0 },
-        { -0.1, -0.1001674211 },
-        { -0.2, -0.2013579207 },
-        { -0.3, -0.3046926540 },
-        { -0.4, -0.4115168460 },
-        { -0.5, -0.5235987755 },
-        { -0.6, -0.6435011087 },
-        { -0.7, -0.7753974966 },
-        { -0.8, -0.9272952180 },
-        { -0.9, -1.1197695149 }
+        { -0.1, -0.10016742116155977 },
+        { -0.2, -0.20135792079033074 },
+        { -0.3, -0.3046926540153976 },
+        { -0.4, -0.41151684606748806 },
+        { -0.5, -0.5235987755982989 },
+        { -0.6, -0.6435011087932844 },
+        { -0.7, -0.775397496610753 },
+        { -0.8, -0.9272952180016123 },
+        { -0.9, -1.1197695149986342 }
     };
     return helper_dtod_inexact("Asin", SDL_asin, precision_cases, SDL_arraysize(precision_cases));
 }
@@ -2495,24 +2518,24 @@ static int
 atan_precisionTest(void *args)
 {
     const d_to_d precision_cases[] = {
-        { 6.313751514675041, 1.4137166941 },
-        { 3.0776835371752527, 1.2566370614 },
-        { 1.9626105055051504, 1.0995574287 },
-        { 1.3763819204711734, 0.9424777960 },
-        { 1.0, 0.7853981633 },
-        { 0.7265425280053609, 0.6283185307 },
-        { 0.5095254494944288, 0.4712388980 },
-        { 0.3249196962329063, 0.3141592653 },
-        { 0.15838444032453627, 0.1570796326 },
-        { -0.15838444032453627, -0.1570796326 },
-        { -0.3249196962329063, -0.3141592653 },
-        { -0.5095254494944288, -0.4712388980 },
-        { -0.7265425280053609, -0.6283185307 },
-        { -1.0, -0.7853981633 },
-        { -1.3763819204711734, -0.9424777960 },
-        { -1.9626105055051504, -1.0995574287 },
-        { -3.0776835371752527, -1.2566370614 },
-        { -6.313751514675041, -1.4137166941 },
+        { 6.313751514675041, 1.413716694115407 },
+        { 3.0776835371752527, 1.2566370614359172 },
+        { 1.9626105055051504, 1.0995574287564276 },
+        { 1.3763819204711734, 0.9424777960769379 },
+        { 1.0, 0.7853981633974483 },
+        { 0.7265425280053609, 0.6283185307179586 },
+        { 0.5095254494944288, 0.47123889803846897 },
+        { 0.3249196962329063, 0.3141592653589793 },
+        { 0.15838444032453627, 0.15707963267948966 },
+        { -0.15838444032453627, -0.15707963267948966 },
+        { -0.3249196962329063, -0.3141592653589793 },
+        { -0.5095254494944288, -0.47123889803846897 },
+        { -0.7265425280053609, -0.6283185307179586 },
+        { -1.0, -0.7853981633974483 },
+        { -1.3763819204711734, -0.9424777960769379 },
+        { -1.9626105055051504, -1.0995574287564276 },
+        { -3.0776835371752527, -1.2566370614359172 },
+        { -6.313751514675041, -1.413716694115407 },
     };
     return helper_dtod_inexact("Atan", SDL_atan, precision_cases, SDL_arraysize(precision_cases));
 }
@@ -2588,29 +2611,12 @@ atan2_xZeroCases(void *args)
 static int
 atan2_bothInfCases(void *args)
 {
-    double result;
-
-    result = SDL_atan2(INFINITY, INFINITY);
-    SDLTest_AssertCheck(SDL_fabs(M_PI / 4.0 - result) <= EPSILON,
-                        "Atan2(%f,%f), expected %f, got %f",
-                        INFINITY, INFINITY, M_PI / 4.0, result);
-
-    result = SDL_atan2(INFINITY, -INFINITY);
-    SDLTest_AssertCheck(SDL_fabs(3.0 * M_PI / 4.0 - result) <= EPSILON,
-                        "Atan2(%f,%f), expected %f, got %f",
-                        INFINITY, -INFINITY, 3.0 * M_PI / 4.0, result);
-
-    result = SDL_atan2(-INFINITY, INFINITY);
-    SDLTest_AssertCheck(SDL_fabs(-M_PI / 4.0 - result) <= EPSILON,
-                        "Atan2(%f,%f), expected %f, got %f",
-                        -INFINITY, INFINITY, -M_PI / 4.0, result);
-
-    result = SDL_atan2(-INFINITY, -INFINITY);
-    SDLTest_AssertCheck(SDL_fabs(-3.0 * M_PI / 4.0 - result) <= EPSILON,
-                        "Atan2(%f,%f), expected %f, got %f",
-                        -INFINITY, -INFINITY, -3.0 * M_PI / 4.0, result);
-
-    return TEST_COMPLETED;
+    dd_to_d cases[4];
+    DD_TO_D_CASE(0,  INFINITY,  INFINITY,  1.0 * M_PI / 4.0);
+    DD_TO_D_CASE(1,  INFINITY, -INFINITY,  3.0 * M_PI / 4.0);
+    DD_TO_D_CASE(2, -INFINITY,  INFINITY, -1.0 * M_PI / 4.0);
+    DD_TO_D_CASE(3, -INFINITY, -INFINITY, -3.0 * M_PI / 4.0);
+    return helper_ddtod("SDL_atan2(bothInfCases)", SDL_atan2, cases, SDL_arraysize(cases));
 }
 
 /**
@@ -2620,29 +2626,12 @@ atan2_bothInfCases(void *args)
 static int
 atan2_yInfCases(void *args)
 {
-    double result;
-
-    result = SDL_atan2(INFINITY, 1.0);
-    SDLTest_AssertCheck(SDL_fabs(M_PI / 2.0 - result) <= EPSILON,
-                        "Atan2(%f,%f), expected %f, got %f",
-                        INFINITY, 1.0, M_PI / 2.0, result);
-
-    result = SDL_atan2(INFINITY, -1.0);
-    SDLTest_AssertCheck(SDL_fabs(M_PI / 2.0 - result) <= EPSILON,
-                        "Atan2(%f,%f), expected %f, got %f",
-                        INFINITY, -1.0, M_PI / 2.0, result);
-
-    result = SDL_atan2(-INFINITY, 1.0);
-    SDLTest_AssertCheck(SDL_fabs(-M_PI / 2.0 - result) <= EPSILON,
-               

(Patch may be truncated, please check the link at the top of this post.)