فهرست منبع

testprograms: parse arguments using SDLTest_CommonState

Anonymous Maarten 2 سال پیش
والد
کامیت
4a6528e3f0
71فایلهای تغییر یافته به همراه1514 افزوده شده و 387 حذف شده
  1. 6 0
      VisualC/tests/gamepadmap/gamepadmap.vcxproj
  2. 6 0
      VisualC/tests/loopwave/loopwave.vcxproj
  3. 6 0
      VisualC/tests/testatomic/testatomic.vcxproj
  4. 6 0
      VisualC/tests/testfile/testfile.vcxproj
  5. 6 0
      VisualC/tests/testgamepad/testgamepad.vcxproj
  6. 6 0
      VisualC/tests/testjoystick/testjoystick.vcxproj
  7. 6 0
      VisualC/tests/testplatform/testplatform.vcxproj
  8. 6 0
      VisualC/tests/testpower/testpower.vcxproj
  9. 6 0
      VisualC/tests/testrumble/testrumble.vcxproj
  10. 6 0
      VisualC/tests/testsensor/testsensor.vcxproj
  11. 6 0
      VisualC/tests/testshape/testshape.vcxproj
  12. 6 0
      VisualC/tests/testsurround/testsurround.vcxproj
  13. 1 0
      VisualC/tests/testyuv/testyuv.vcxproj
  14. 34 24
      test/CMakeLists.txt
  15. 15 1
      test/checkkeys.c
  16. 14 0
      test/checkkeysthreads.c
  17. 30 4
      test/gamepadmap.c
  18. 30 1
      test/loopwave.c
  19. 32 2
      test/loopwavequeue.c
  20. 15 0
      test/testatomic.c
  21. 39 5
      test/testaudiocapture.c
  22. 39 3
      test/testaudiohotplug.c
  23. 15 1
      test/testaudioinfo.c
  24. 14 0
      test/testbounds.c
  25. 14 0
      test/testdisplayinfo.c
  26. 15 0
      test/testdrawchessboard.c
  27. 3 3
      test/testdropfile.c
  28. 14 0
      test/testerror.c
  29. 19 1
      test/testevdev.c
  30. 16 0
      test/testfile.c
  31. 14 0
      test/testfilesystem.c
  32. 51 23
      test/testgamepad.c
  33. 4 3
      test/testgeometry.c
  34. 5 4
      test/testgl.c
  35. 11 5
      test/testgles.c
  36. 7 2
      test/testgles2.c
  37. 7 2
      test/testgles2_sdf.c
  38. 36 17
      test/testhaptic.c
  39. 29 3
      test/testhotplug.c
  40. 31 2
      test/testiconv.c
  41. 22 25
      test/testime.c
  42. 23 5
      test/testjoystick.c
  43. 14 0
      test/testkeys.c
  44. 50 13
      test/testloadso.c
  45. 56 19
      test/testlocale.c
  46. 14 0
      test/testmessage.c
  47. 34 14
      test/testmouse.c
  48. 40 6
      test/testmultiaudio.c
  49. 14 0
      test/testnative.c
  50. 8 0
      test/testnative.h
  51. 14 0
      test/testoffscreen.c
  52. 30 2
      test/testplatform.c
  53. 8 0
      test/testpopup.c
  54. 17 1
      test/testpower.c
  55. 45 17
      test/testqsort.c
  56. 5 2
      test/testrelative.c
  57. 3 3
      test/testrendercopyex.c
  58. 64 10
      test/testresample.c
  59. 38 15
      test/testrumble.c
  60. 9 5
      test/testscale.c
  61. 40 2
      test/testsem.c
  62. 18 0
      test/testsensor.c
  63. 37 1
      test/testshader.c
  64. 101 74
      test/testshape.c
  65. 14 0
      test/teststreaming.c
  66. 13 0
      test/testsurround.c
  67. 36 6
      test/testtimer.c
  68. 3 3
      test/testvulkan.c
  69. 5 5
      test/testwm.c
  70. 99 53
      test/testyuv.c
  71. 14 0
      test/torturethread.c

+ 6 - 0
VisualC/tests/gamepadmap/gamepadmap.vcxproj

@@ -188,6 +188,12 @@
       <CopyLocalSatelliteAssemblies>false</CopyLocalSatelliteAssemblies>
       <ReferenceOutputAssembly>true</ReferenceOutputAssembly>
     </ProjectReference>
+    <ProjectReference Include="..\..\SDL_test\SDL_test.vcxproj">
+      <Project>{da956fd3-e143-46f2-9fe5-c77bebc56b1a}</Project>
+      <Private>false</Private>
+      <CopyLocalSatelliteAssemblies>false</CopyLocalSatelliteAssemblies>
+      <ReferenceOutputAssembly>true</ReferenceOutputAssembly>
+    </ProjectReference>
   </ItemGroup>
   <ItemGroup>
     <CustomBuild Include="..\..\..\test\axis.bmp">

+ 6 - 0
VisualC/tests/loopwave/loopwave.vcxproj

@@ -194,6 +194,12 @@
       <CopyLocalSatelliteAssemblies>false</CopyLocalSatelliteAssemblies>
       <ReferenceOutputAssembly>true</ReferenceOutputAssembly>
     </ProjectReference>
+    <ProjectReference Include="..\..\SDL_test\SDL_test.vcxproj">
+      <Project>{da956fd3-e143-46f2-9fe5-c77bebc56b1a}</Project>
+      <Private>false</Private>
+      <CopyLocalSatelliteAssemblies>false</CopyLocalSatelliteAssemblies>
+      <ReferenceOutputAssembly>true</ReferenceOutputAssembly>
+    </ProjectReference>
   </ItemGroup>
   <ItemGroup>
     <ClCompile Include="..\..\..\Test\loopwave.c" />

+ 6 - 0
VisualC/tests/testatomic/testatomic.vcxproj

@@ -188,6 +188,12 @@
       <CopyLocalSatelliteAssemblies>false</CopyLocalSatelliteAssemblies>
       <ReferenceOutputAssembly>true</ReferenceOutputAssembly>
     </ProjectReference>
+    <ProjectReference Include="..\..\SDL_test\SDL_test.vcxproj">
+      <Project>{da956fd3-e143-46f2-9fe5-c77bebc56b1a}</Project>
+      <Private>false</Private>
+      <CopyLocalSatelliteAssemblies>false</CopyLocalSatelliteAssemblies>
+      <ReferenceOutputAssembly>true</ReferenceOutputAssembly>
+    </ProjectReference>
   </ItemGroup>
   <ItemGroup>
     <ClCompile Include="..\..\..\test\testatomic.c" />

+ 6 - 0
VisualC/tests/testfile/testfile.vcxproj

@@ -188,6 +188,12 @@
       <CopyLocalSatelliteAssemblies>false</CopyLocalSatelliteAssemblies>
       <ReferenceOutputAssembly>true</ReferenceOutputAssembly>
     </ProjectReference>
+    <ProjectReference Include="..\..\SDL_test\SDL_test.vcxproj">
+      <Project>{da956fd3-e143-46f2-9fe5-c77bebc56b1a}</Project>
+      <Private>false</Private>
+      <CopyLocalSatelliteAssemblies>false</CopyLocalSatelliteAssemblies>
+      <ReferenceOutputAssembly>true</ReferenceOutputAssembly>
+    </ProjectReference>
   </ItemGroup>
   <ItemGroup>
     <ClCompile Include="..\..\..\Test\testfile.c" />

+ 6 - 0
VisualC/tests/testgamepad/testgamepad.vcxproj

@@ -188,6 +188,12 @@
       <CopyLocalSatelliteAssemblies>false</CopyLocalSatelliteAssemblies>
       <ReferenceOutputAssembly>true</ReferenceOutputAssembly>
     </ProjectReference>
+    <ProjectReference Include="..\..\SDL_test\SDL_test.vcxproj">
+      <Project>{da956fd3-e143-46f2-9fe5-c77bebc56b1a}</Project>
+      <Private>false</Private>
+      <CopyLocalSatelliteAssemblies>false</CopyLocalSatelliteAssemblies>
+      <ReferenceOutputAssembly>true</ReferenceOutputAssembly>
+    </ProjectReference>
   </ItemGroup>
   <ItemGroup>
     <CustomBuild Include="..\..\..\test\axis.bmp">

+ 6 - 0
VisualC/tests/testjoystick/testjoystick.vcxproj

@@ -188,6 +188,12 @@
       <CopyLocalSatelliteAssemblies>false</CopyLocalSatelliteAssemblies>
       <ReferenceOutputAssembly>true</ReferenceOutputAssembly>
     </ProjectReference>
+    <ProjectReference Include="..\..\SDL_test\SDL_test.vcxproj">
+      <Project>{da956fd3-e143-46f2-9fe5-c77bebc56b1a}</Project>
+      <Private>false</Private>
+      <CopyLocalSatelliteAssemblies>false</CopyLocalSatelliteAssemblies>
+      <ReferenceOutputAssembly>true</ReferenceOutputAssembly>
+    </ProjectReference>
   </ItemGroup>
   <ItemGroup>
     <ClCompile Include="..\..\..\test\testjoystick.c" />

+ 6 - 0
VisualC/tests/testplatform/testplatform.vcxproj

@@ -216,6 +216,12 @@
       <CopyLocalSatelliteAssemblies>false</CopyLocalSatelliteAssemblies>
       <ReferenceOutputAssembly>true</ReferenceOutputAssembly>
     </ProjectReference>
+    <ProjectReference Include="..\..\SDL_test\SDL_test.vcxproj">
+      <Project>{da956fd3-e143-46f2-9fe5-c77bebc56b1a}</Project>
+      <Private>false</Private>
+      <CopyLocalSatelliteAssemblies>false</CopyLocalSatelliteAssemblies>
+      <ReferenceOutputAssembly>true</ReferenceOutputAssembly>
+    </ProjectReference>
   </ItemGroup>
   <ItemGroup>
     <ClCompile Include="..\..\..\Test\testplatform.c" />

+ 6 - 0
VisualC/tests/testpower/testpower.vcxproj

@@ -188,6 +188,12 @@
       <CopyLocalSatelliteAssemblies>false</CopyLocalSatelliteAssemblies>
       <ReferenceOutputAssembly>true</ReferenceOutputAssembly>
     </ProjectReference>
+    <ProjectReference Include="..\..\SDL_test\SDL_test.vcxproj">
+      <Project>{da956fd3-e143-46f2-9fe5-c77bebc56b1a}</Project>
+      <Private>false</Private>
+      <CopyLocalSatelliteAssemblies>false</CopyLocalSatelliteAssemblies>
+      <ReferenceOutputAssembly>true</ReferenceOutputAssembly>
+    </ProjectReference>
   </ItemGroup>
   <ItemGroup>
     <ClCompile Include="..\..\..\test\testpower.c" />

+ 6 - 0
VisualC/tests/testrumble/testrumble.vcxproj

@@ -188,6 +188,12 @@
       <CopyLocalSatelliteAssemblies>false</CopyLocalSatelliteAssemblies>
       <ReferenceOutputAssembly>true</ReferenceOutputAssembly>
     </ProjectReference>
+    <ProjectReference Include="..\..\SDL_test\SDL_test.vcxproj">
+      <Project>{da956fd3-e143-46f2-9fe5-c77bebc56b1a}</Project>
+      <Private>false</Private>
+      <CopyLocalSatelliteAssemblies>false</CopyLocalSatelliteAssemblies>
+      <ReferenceOutputAssembly>true</ReferenceOutputAssembly>
+    </ProjectReference>
   </ItemGroup>
   <ItemGroup>
     <ClCompile Include="..\..\..\test\testrumble.c" />

+ 6 - 0
VisualC/tests/testsensor/testsensor.vcxproj

@@ -188,6 +188,12 @@
       <CopyLocalSatelliteAssemblies>false</CopyLocalSatelliteAssemblies>
       <ReferenceOutputAssembly>true</ReferenceOutputAssembly>
     </ProjectReference>
+    <ProjectReference Include="..\..\SDL_test\SDL_test.vcxproj">
+      <Project>{da956fd3-e143-46f2-9fe5-c77bebc56b1a}</Project>
+      <Private>false</Private>
+      <CopyLocalSatelliteAssemblies>false</CopyLocalSatelliteAssemblies>
+      <ReferenceOutputAssembly>true</ReferenceOutputAssembly>
+    </ProjectReference>
   </ItemGroup>
   <ItemGroup>
     <ClCompile Include="..\..\..\test\testsensor.c" />

+ 6 - 0
VisualC/tests/testshape/testshape.vcxproj

@@ -188,6 +188,12 @@
       <CopyLocalSatelliteAssemblies>false</CopyLocalSatelliteAssemblies>
       <ReferenceOutputAssembly>true</ReferenceOutputAssembly>
     </ProjectReference>
+    <ProjectReference Include="..\..\SDL_test\SDL_test.vcxproj">
+      <Project>{da956fd3-e143-46f2-9fe5-c77bebc56b1a}</Project>
+      <Private>false</Private>
+      <CopyLocalSatelliteAssemblies>false</CopyLocalSatelliteAssemblies>
+      <ReferenceOutputAssembly>true</ReferenceOutputAssembly>
+    </ProjectReference>
   </ItemGroup>
   <ItemGroup>
     <ClCompile Include="..\..\..\test\testshape.c" />

+ 6 - 0
VisualC/tests/testsurround/testsurround.vcxproj

@@ -194,6 +194,12 @@
       <CopyLocalSatelliteAssemblies>false</CopyLocalSatelliteAssemblies>
       <ReferenceOutputAssembly>true</ReferenceOutputAssembly>
     </ProjectReference>
+    <ProjectReference Include="..\..\SDL_test\SDL_test.vcxproj">
+      <Project>{da956fd3-e143-46f2-9fe5-c77bebc56b1a}</Project>
+      <Private>false</Private>
+      <CopyLocalSatelliteAssemblies>false</CopyLocalSatelliteAssemblies>
+      <ReferenceOutputAssembly>true</ReferenceOutputAssembly>
+    </ProjectReference>
   </ItemGroup>
   <ItemGroup>
     <ClCompile Include="..\..\..\Test\testsurround.c" />

+ 1 - 0
VisualC/tests/testyuv/testyuv.vcxproj

@@ -218,6 +218,7 @@
   <ItemGroup>
     <ClCompile Include="..\..\..\test\testyuv.c" />
     <ClCompile Include="..\..\..\test\testyuv_cvt.c" />
+    <ClCompile Include="..\..\..\test\testutils.c" />
   </ItemGroup>
   <ItemGroup>
     <ClInclude Include="..\..\..\test\testyuv_cvt.h" />

+ 34 - 24
test/CMakeLists.txt

@@ -136,9 +136,39 @@ add_sdl_test_executable(testdropfile testdropfile.c)
 add_sdl_test_executable(testerror NONINTERACTIVE testerror.c)
 
 if(LINUX AND TARGET sdl-build-options)
+    set(build_options_dependent_tests )
+
     add_sdl_test_executable(testevdev NONINTERACTIVE testevdev.c)
-    target_include_directories(testevdev BEFORE PRIVATE $<TARGET_PROPERTY:sdl-build-options,INTERFACE_INCLUDE_DIRECTORIES>)
-    target_include_directories(testevdev BEFORE PRIVATE ${SDL3_SOURCE_DIR}/src)
+    list(APPEND build_options_dependent_tests testevdev)
+
+    if(APPLE)
+        add_sdl_test_executable(testnative NEEDS_RESOURCES TESTUTILS
+            testnative.c
+            testnativecocoa.m
+            testnativex11.c
+        )
+        target_compile_definitions(testnative PRIVATE TEST_NATIVE_COCOA)
+
+        cmake_push_check_state()
+        check_c_compiler_flag(-Wno-error=deprecated-declarations HAVE_WNO_ERROR_DEPRECATED_DECLARATIONS)
+        cmake_pop_check_state()
+        if(HAVE_WNO_ERROR_DEPRECATED_DECLARATIONS)
+            set_property(SOURCE "testnativecocoa.m" APPEND_STRING PROPERTY COMPILE_FLAGS " -Wno-error=deprecated-declarations")
+        endif()
+        list(APPEND build_options_dependent_tests testnative)
+    elseif(WINDOWS)
+        add_sdl_test_executable(testnative NEEDS_RESOURCES TESTUTILS testnative.c testnativew32.c)
+        list(APPEND build_options_dependent_tests testnative)
+    elseif(HAVE_X11)
+        add_sdl_test_executable(testnative NEEDS_RESOURCES TESTUTILS testnative.c testnativex11.c)
+        target_link_libraries(testnative PRIVATE X11)
+        list(APPEND build_options_dependent_tests testnative)
+    endif()
+
+    foreach(t ${build_options_dependent_tests})
+        target_include_directories(${t} BEFORE PRIVATE $<TARGET_PROPERTY:sdl-build-options,INTERFACE_INCLUDE_DIRECTORIES>)
+        target_include_directories(${t} BEFORE PRIVATE ${SDL3_SOURCE_DIR}/src)
+    endforeach()
 endif()
 
 add_sdl_test_executable(testfile testfile.c)
@@ -161,26 +191,6 @@ add_sdl_test_executable(testlocale NONINTERACTIVE testlocale.c)
 add_sdl_test_executable(testlock testlock.c)
 add_sdl_test_executable(testmouse testmouse.c)
 
-if(APPLE)
-    add_sdl_test_executable(testnative NEEDS_RESOURCES TESTUTILS
-        testnative.c
-        testnativecocoa.m
-        testnativex11.c
-    )
-
-    cmake_push_check_state()
-    check_c_compiler_flag(-Wno-error=deprecated-declarations HAVE_WNO_ERROR_DEPRECATED_DECLARATIONS)
-    cmake_pop_check_state()
-    if(HAVE_WNO_ERROR_DEPRECATED_DECLARATIONS)
-        set_property(SOURCE "testnativecocoa.m" APPEND_STRING PROPERTY COMPILE_FLAGS " -Wno-error=deprecated-declarations")
-    endif()
-elseif(WINDOWS)
-    add_sdl_test_executable(testnative NEEDS_RESOURCES TESTUTILS testnative.c testnativew32.c)
-elseif(HAVE_X11)
-    add_sdl_test_executable(testnative NEEDS_RESOURCES TESTUTILS testnative.c testnativex11.c)
-    target_link_libraries(testnative PRIVATE X11)
-endif()
-
 add_sdl_test_executable(testoverlay NEEDS_RESOURCES TESTUTILS testoverlay.c)
 add_sdl_test_executable(testplatform NONINTERACTIVE testplatform.c)
 add_sdl_test_executable(testpower NONINTERACTIVE testpower.c)
@@ -189,7 +199,7 @@ add_sdl_test_executable(testrendertarget NEEDS_RESOURCES TESTUTILS testrendertar
 add_sdl_test_executable(testscale NEEDS_RESOURCES TESTUTILS testscale.c)
 add_sdl_test_executable(testsem testsem.c)
 add_sdl_test_executable(testsensor testsensor.c)
-add_sdl_test_executable(testshader NEEDS_RESOURCES testshader.c)
+add_sdl_test_executable(testshader NEEDS_RESOURCES TESTUTILS testshader.c)
 add_sdl_test_executable(testshape NEEDS_RESOURCES testshape.c)
 add_sdl_test_executable(testsprite NEEDS_RESOURCES TESTUTILS testsprite.c)
 add_sdl_test_executable(testspriteminimal NEEDS_RESOURCES TESTUTILS testspriteminimal.c)
@@ -199,7 +209,7 @@ add_sdl_test_executable(testurl testurl.c)
 add_sdl_test_executable(testver NONINTERACTIVE testver.c)
 add_sdl_test_executable(testviewport NEEDS_RESOURCES TESTUTILS testviewport.c)
 add_sdl_test_executable(testwm testwm.c)
-add_sdl_test_executable(testyuv NEEDS_RESOURCES testyuv.c testyuv_cvt.c)
+add_sdl_test_executable(testyuv NEEDS_RESOURCES TESTUTILS testyuv.c testyuv_cvt.c)
 add_sdl_test_executable(torturethread torturethread.c)
 add_sdl_test_executable(testrendercopyex NEEDS_RESOURCES TESTUTILS testrendercopyex.c)
 add_sdl_test_executable(testmessage testmessage.c)

+ 15 - 1
test/checkkeys.c

@@ -23,7 +23,7 @@
 
 #include <SDL3/SDL.h>
 #include <SDL3/SDL_main.h>
-#include <SDL3/SDL_test_font.h>
+#include <SDL3/SDL_test.h>
 
 static SDL_Window *window;
 static SDL_Renderer *renderer;
@@ -249,9 +249,22 @@ static void loop(void)
 
 int main(int argc, char *argv[])
 {
+    SDLTest_CommonState *state;
+
+    /* Initialize test framework */
+    state = SDLTest_CommonCreateState(argv, 0);
+    if (state == NULL) {
+        return 1;
+    }
+
     /* Enable standard application logging */
     SDL_LogSetPriority(SDL_LOG_CATEGORY_APPLICATION, SDL_LOG_PRIORITY_INFO);
 
+    /* Parse commandline */
+    if (!SDLTest_CommonDefaultArgs(state, argc, argv)) {
+        return 1;
+    }
+
     /* Disable mouse emulation */
     SDL_SetHint(SDL_HINT_TOUCH_MOUSE_EVENTS, "0");
 
@@ -304,5 +317,6 @@ int main(int argc, char *argv[])
 #endif
 
     SDL_Quit();
+    SDLTest_CommonDestroyState(state);
     return 0;
 }

+ 14 - 0
test/checkkeysthreads.c

@@ -24,6 +24,7 @@
 
 #include <SDL3/SDL.h>
 #include <SDL3/SDL_main.h>
+#include <SDL3/SDL_test.h>
 
 static int done;
 
@@ -240,10 +241,22 @@ int main(int argc, char *argv[])
     SDL_Window *window;
     SDL_Renderer *renderer;
     SDL_Thread *thread;
+    SDLTest_CommonState *state;
+
+    /* Initialize test framework */
+    state = SDLTest_CommonCreateState(argv, 0);
+    if (state == NULL) {
+        return 1;
+    }
 
     /* Enable standard application logging */
     SDL_LogSetPriority(SDL_LOG_CATEGORY_APPLICATION, SDL_LOG_PRIORITY_INFO);
 
+    /* Parse commandline */
+    if (!SDLTest_CommonDefaultArgs(state, argc, argv)) {
+        return 1;
+    }
+
     /* Initialize SDL */
     if (SDL_Init(SDL_INIT_VIDEO) < 0) {
         SDL_LogError(SDL_LOG_CATEGORY_APPLICATION, "Couldn't initialize SDL: %s\n", SDL_GetError());
@@ -290,5 +303,6 @@ int main(int argc, char *argv[])
 
     SDL_WaitThread(thread, NULL);
     SDL_Quit();
+    SDLTest_CommonDestroyState(state);
     return 0;
 }

+ 30 - 4
test/gamepadmap.c

@@ -18,6 +18,7 @@
 
 #include <SDL3/SDL.h>
 #include <SDL3/SDL_main.h>
+#include <SDL3/SDL_test.h>
 #include "testutils.h"
 
 /* Define this for verbose output while mapping gamepads */
@@ -729,22 +730,45 @@ int main(int argc, char *argv[])
     SDL_JoystickID *joysticks;
     int joystick_index;
     SDL_Joystick *joystick = NULL;
+    SDLTest_CommonState *state;
 
     SDL_SetHint(SDL_HINT_ACCELEROMETER_AS_JOYSTICK, "0");
 
+    /* Initialize test framework */
+    state = SDLTest_CommonCreateState(argv, 0);
+    if (state == NULL) {
+        return 1;
+    }
+
     /* Enable standard application logging */
     SDL_LogSetPriority(SDL_LOG_CATEGORY_APPLICATION, SDL_LOG_PRIORITY_INFO);
 
+    /* Parse commandline */
+    for (i = 1; i < argc;) {
+        int consumed;
+
+        consumed = SDLTest_CommonArg(state, i);
+        if (!consumed) {
+            if (SDL_strcmp(argv[i], "--bind-touchpad") == 0) {
+                bind_touchpad = SDL_TRUE;
+                consumed = 1;
+            }
+        }
+        if (consumed <= 0) {
+            static const char *options[] = { "[--bind-touchpad]", NULL };
+            SDLTest_CommonLogUsage(state, argv[0], options);
+            exit(1);
+        }
+
+        i += consumed;
+    }
+
     /* Initialize SDL (Note: video is required to start event loop) */
     if (SDL_Init(SDL_INIT_VIDEO | SDL_INIT_JOYSTICK) < 0) {
         SDL_LogError(SDL_LOG_CATEGORY_APPLICATION, "Couldn't initialize SDL: %s\n", SDL_GetError());
         exit(1);
     }
 
-    if (argv[1] && SDL_strcmp(argv[1], "--bind-touchpad") == 0) {
-        bind_touchpad = SDL_TRUE;
-    }
-
     /* Create a window to display joystick axis position */
     window = SDL_CreateWindow("Game Controller Map", SCREEN_WIDTH, SCREEN_HEIGHT, 0);
     if (window == NULL) {
@@ -830,5 +854,7 @@ int main(int argc, char *argv[])
 
     SDL_QuitSubSystem(SDL_INIT_VIDEO | SDL_INIT_JOYSTICK);
 
+    SDLTest_CommonDestroyState(state);
+
     return 0;
 }

+ 30 - 1
test/loopwave.c

@@ -23,6 +23,7 @@
 
 #include <SDL3/SDL.h>
 #include <SDL3/SDL_main.h>
+#include <SDL3/SDL_test.h>
 #include "testutils.h"
 
 static struct
@@ -113,17 +114,44 @@ int main(int argc, char *argv[])
 {
     int i;
     char *filename = NULL;
+    SDLTest_CommonState *state;
+
+    /* Initialize test framework */
+    state = SDLTest_CommonCreateState(argv, 0);
+    if (state == NULL) {
+        return 1;
+    }
 
     /* Enable standard application logging */
     SDL_LogSetPriority(SDL_LOG_CATEGORY_APPLICATION, SDL_LOG_PRIORITY_INFO);
 
+    /* Parse commandline */
+    for (i = 1; i < argc;) {
+        int consumed;
+
+        consumed = SDLTest_CommonArg(state, i);
+        if (!consumed) {
+            if (!filename) {
+                filename = argv[i];
+                consumed = 1;
+            }
+        }
+        if (consumed <= 0) {
+            static const char *options[] = { "[sample.wav]", NULL };
+            SDLTest_CommonLogUsage(state, argv[0], options);
+            exit(1);
+        }
+
+        i += consumed;
+    }
+
     /* Load the SDL library */
     if (SDL_Init(SDL_INIT_AUDIO | SDL_INIT_EVENTS) < 0) {
         SDL_LogError(SDL_LOG_CATEGORY_APPLICATION, "Couldn't initialize SDL: %s\n", SDL_GetError());
         return 1;
     }
 
-    filename = GetResourceFilename(argc > 1 ? argv[1] : NULL, "sample.wav");
+    filename = GetResourceFilename(filename, "sample.wav");
 
     if (filename == NULL) {
         SDL_LogError(SDL_LOG_CATEGORY_APPLICATION, "%s\n", SDL_GetError());
@@ -174,5 +202,6 @@ int main(int argc, char *argv[])
     SDL_free(wave.sound);
     SDL_free(filename);
     SDL_Quit();
+    SDLTest_CommonDestroyState(state);
     return 0;
 }

+ 32 - 2
test/loopwavequeue.c

@@ -20,6 +20,7 @@
 
 #include <SDL3/SDL.h>
 #include <SDL3/SDL_main.h>
+#include <SDL3/SDL_test.h>
 
 #if HAVE_SIGNAL_H
 #include <signal.h>
@@ -73,18 +74,46 @@ static void loop(void)
 
 int main(int argc, char *argv[])
 {
+    int i;
     char *filename = NULL;
+    SDLTest_CommonState *state;
+
+    /* Initialize test framework */
+    state = SDLTest_CommonCreateState(argv, 0);
+    if (state == NULL) {
+        return 1;
+    }
 
     /* Enable standard application logging */
     SDL_LogSetPriority(SDL_LOG_CATEGORY_APPLICATION, SDL_LOG_PRIORITY_INFO);
 
+    /* Parse commandline */
+    for (i = 1; i < argc;) {
+        int consumed;
+
+        consumed = SDLTest_CommonArg(state, i);
+        if (!consumed) {
+            if (!filename) {
+                filename = argv[i];
+                consumed = 1;
+            }
+        }
+        if (consumed <= 0) {
+            static const char *options[] = { "[sample.wav]", NULL };
+            SDLTest_CommonLogUsage(state, argv[0], options);
+            exit(1);
+        }
+
+        i += consumed;
+    }
+
     /* Load the SDL library */
     if (SDL_Init(SDL_INIT_AUDIO) < 0) {
         SDL_LogError(SDL_LOG_CATEGORY_APPLICATION, "Couldn't initialize SDL: %s\n", SDL_GetError());
         return 1;
     }
 
-    filename = GetResourceFilename(argc > 1 ? argv[1] : NULL, "sample.wav");
+    filename = GetResourceFilename(filename, "sample.wav");
 
     if (filename == NULL) {
         SDL_LogError(SDL_LOG_CATEGORY_APPLICATION, "%s\n", SDL_GetError());
@@ -137,7 +166,7 @@ int main(int argc, char *argv[])
     while (!done && (SDL_GetAudioDeviceStatus(g_audio_id) == SDL_AUDIO_PLAYING)) {
         loop();
 
-        SDL_Delay(100); /* let it play for awhile. */
+        SDL_Delay(100); /* let it play for a while. */
     }
 #endif
 
@@ -146,5 +175,6 @@ int main(int argc, char *argv[])
     SDL_free(wave.sound);
     SDL_free(filename);
     SDL_Quit();
+    SDLTest_CommonDestroyState(state);
     return 0;
 }

+ 15 - 0
test/testatomic.c

@@ -12,6 +12,7 @@
 
 #include <SDL3/SDL.h>
 #include <SDL3/SDL_main.h>
+#include <SDL3/SDL_test.h>
 
 /*
   Absolutely basic tests just to see if we get the expected value
@@ -695,9 +696,22 @@ static void RunFIFOTest(SDL_bool lock_free)
 
 int main(int argc, char *argv[])
 {
+    SDLTest_CommonState *state;
+
+    /* Initialize test framework */
+    state = SDLTest_CommonCreateState(argv, 0);
+    if (state == NULL) {
+        return 1;
+    }
+
     /* Enable standard application logging */
     SDL_LogSetPriority(SDL_LOG_CATEGORY_APPLICATION, SDL_LOG_PRIORITY_INFO);
 
+    /* Parse commandline */
+    if (!SDLTest_CommonDefaultArgs(state, argc, argv)) {
+        return 1;
+    }
+
     RunBasicTest();
 
     if (SDL_getenv("SDL_TESTS_QUICK") != NULL) {
@@ -711,5 +725,6 @@ int main(int argc, char *argv[])
     RunFIFOTest(SDL_FALSE);
 #endif
     RunFIFOTest(SDL_TRUE);
+    SDLTest_CommonDestroyState(state);
     return 0;
 }

+ 39 - 5
test/testaudiocapture.c

@@ -14,6 +14,7 @@
 
 #include <SDL3/SDL.h>
 #include <SDL3/SDL_main.h>
+#include <SDL3/SDL_test.h>
 
 #ifdef __EMSCRIPTEN__
 #include <emscripten/emscripten.h>
@@ -89,23 +90,52 @@ static void loop(void)
 
 int main(int argc, char **argv)
 {
-    /* (argv[1] == NULL means "open default device.") */
-    const char *devname = argv[1];
+    /* (NULL means "open default device.") */
+    const char *devname = NULL;
     SDL_AudioSpec wanted;
     int devcount;
     int i;
+    SDLTest_CommonState *state;
+
+    /* Initialize test framework */
+    state = SDLTest_CommonCreateState(argv, 0);
+    if (state == NULL) {
+        return 1;
+    }
 
     /* Enable standard application logging */
     SDL_LogSetPriority(SDL_LOG_CATEGORY_APPLICATION, SDL_LOG_PRIORITY_INFO);
 
+    /* Parse commandline */
+    for (i = 1; i < argc;) {
+        int consumed;
+
+        consumed = SDLTest_CommonArg(state, i);
+        if (!consumed) {
+            if (!devname) {
+                devname = argv[i];
+                consumed = 1;
+            }
+        }
+        if (consumed <= 0) {
+            static const char *options[] = { "[driver_name]", NULL };
+            SDLTest_CommonLogUsage(state, argv[0], options);
+            exit(1);
+        }
+
+        i += consumed;
+    }
+
     /* Load the SDL library */
     if (SDL_Init(SDL_INIT_VIDEO | SDL_INIT_AUDIO) < 0) {
         SDL_LogError(SDL_LOG_CATEGORY_APPLICATION, "Couldn't initialize SDL: %s\n", SDL_GetError());
         return 1;
     }
 
-    window = SDL_CreateWindow("testaudiocapture", 320, 240, 0);
-    renderer = SDL_CreateRenderer(window, NULL, 0);
+    if (SDL_CreateWindowAndRenderer(320, 240, 0, &window, &renderer) < 0) {
+        SDL_LogError(SDL_LOG_CATEGORY_APPLICATION, "Couldn't create SDL window and renderer: %s\n", SDL_GetError());
+        return 1;
+    }
     SDL_SetRenderDrawColor(renderer, 0, 0, 0, 255);
     SDL_RenderClear(renderer);
     SDL_RenderPresent(renderer);
@@ -145,7 +175,7 @@ int main(int argc, char **argv)
             devname ? devname : "[[default]]",
             devname ? "'" : "");
 
-    devid_in = SDL_OpenAudioDevice(argv[1], SDL_TRUE, &spec, &spec, 0);
+    devid_in = SDL_OpenAudioDevice(devname, SDL_TRUE, &spec, &spec, 0);
     if (!devid_in) {
         SDL_LogError(SDL_LOG_CATEGORY_APPLICATION, "Couldn't open an audio device for capture: %s!\n", SDL_GetError());
         SDL_Quit();
@@ -162,6 +192,10 @@ int main(int argc, char **argv)
         SDL_Delay(16);
     }
 #endif
+    /* SDL_DestroyRenderer(renderer); */
+    /* SDL_DestroyWindow(window); */
 
+    /* SDL_Quit(); */
+    /* SDLTest_CommonDestroyState(state); */
     /* return 0; */
 }

+ 39 - 3
test/testaudiohotplug.c

@@ -24,6 +24,7 @@
 
 #include <SDL3/SDL.h>
 #include <SDL3/SDL_main.h>
+#include <SDL3/SDL_test.h>
 #include "testutils.h"
 
 static SDL_AudioSpec spec;
@@ -33,11 +34,14 @@ static Uint32 soundlen = 0; /* Length of wave data */
 static int posindex = 0;
 static Uint32 positions[64];
 
+static SDLTest_CommonState *state;
+
 /* Call this instead of exit(), so we can clean up SDL: atexit() is evil. */
 static void
 quit(int rc)
 {
     SDL_Quit();
+    SDLTest_CommonDestroyState(state);
     exit(rc);
 }
 
@@ -134,10 +138,37 @@ int main(int argc, char *argv[])
 {
     int i;
     char *filename = NULL;
+    SDL_Window *window;
+
+    /* Initialize test framework */
+    state = SDLTest_CommonCreateState(argv, 0);
+    if (state == NULL) {
+        return 1;
+    }
 
     /* Enable standard application logging */
     SDL_LogSetPriority(SDL_LOG_CATEGORY_APPLICATION, SDL_LOG_PRIORITY_INFO);
 
+    /* Parse commandline */
+    for (i = 1; i < argc;) {
+        int consumed;
+
+        consumed = SDLTest_CommonArg(state, i);
+        if (!consumed) {
+            if (!filename) {
+                filename = argv[i];
+                consumed = 1;
+            }
+        }
+        if (consumed <= 0) {
+            static const char *options[] = { "[sample.wav]", NULL };
+            SDLTest_CommonLogUsage(state, argv[0], options);
+            exit(1);
+        }
+
+        i += consumed;
+    }
+
     /* Load the SDL library */
     if (SDL_Init(SDL_INIT_VIDEO | SDL_INIT_AUDIO) < 0) {
         SDL_LogError(SDL_LOG_CATEGORY_APPLICATION, "Couldn't initialize SDL: %s\n", SDL_GetError());
@@ -145,9 +176,14 @@ int main(int argc, char *argv[])
     }
 
     /* Some targets (Mac CoreAudio) need an event queue for audio hotplug, so make and immediately hide a window. */
-    SDL_MinimizeWindow(SDL_CreateWindow("testaudiohotplug", 640, 480, 0));
+    window = SDL_CreateWindow("testaudiohotplug", 640, 480, 0);
+    if (window == NULL) {
+        SDL_LogError(SDL_LOG_CATEGORY_APPLICATION, "SDL_CreateWindow failed: %s\n", SDL_GetError());
+        quit(1);
+    }
+    SDL_MinimizeWindow(window);
 
-    filename = GetResourceFilename(argc > 1 ? argv[1] : NULL, "sample.wav");
+    filename = GetResourceFilename(filename, "sample.wav");
 
     if (filename == NULL) {
         SDL_LogError(SDL_LOG_CATEGORY_APPLICATION, "%s\n", SDL_GetError());
@@ -195,6 +231,6 @@ int main(int argc, char *argv[])
     SDL_QuitSubSystem(SDL_INIT_AUDIO);
     SDL_free(sound);
     SDL_free(filename);
-    SDL_Quit();
+    quit(0);
     return 0;
 }

+ 15 - 1
test/testaudioinfo.c

@@ -11,6 +11,7 @@
 */
 #include <SDL3/SDL.h>
 #include <SDL3/SDL_main.h>
+#include <SDL3/SDL_test.h>
 
 static void
 print_devices(int iscapture)
@@ -49,11 +50,24 @@ int main(int argc, char **argv)
 {
     char *deviceName = NULL;
     SDL_AudioSpec spec;
+    int i;
     int n;
+    SDLTest_CommonState *state;
+
+    /* Initialize test framework */
+    state = SDLTest_CommonCreateState(argv, 0);
+    if (state == NULL) {
+        return 1;
+    }
 
     /* Enable standard application logging */
     SDL_LogSetPriority(SDL_LOG_CATEGORY_APPLICATION, SDL_LOG_PRIORITY_INFO);
 
+    /* Parse commandline */
+    if (!SDLTest_CommonDefaultArgs(state, argc, argv)) {
+        return 1;
+    }
+
     /* Load the SDL library */
     if (SDL_Init(SDL_INIT_AUDIO) < 0) {
         SDL_LogError(SDL_LOG_CATEGORY_APPLICATION, "Couldn't initialize SDL: %s\n", SDL_GetError());
@@ -65,7 +79,6 @@ int main(int argc, char **argv)
     if (n == 0) {
         SDL_Log("No built-in audio drivers\n\n");
     } else {
-        int i;
         SDL_Log("Built-in audio drivers:\n");
         for (i = 0; i < n; ++i) {
             SDL_Log("  %d: %s\n", i, SDL_GetAudioDriver(i));
@@ -99,5 +112,6 @@ int main(int argc, char **argv)
     }
 
     SDL_Quit();
+    SDLTest_CommonDestroyState(state);
     return 0;
 }

+ 14 - 0
test/testbounds.c

@@ -12,11 +12,24 @@
 
 #include <SDL3/SDL.h>
 #include <SDL3/SDL_main.h>
+#include <SDL3/SDL_test.h>
 
 int main(int argc, char **argv)
 {
     SDL_DisplayID *displays;
     int i;
+    SDLTest_CommonState *state;
+
+    /* Initialize test framework */
+    state = SDLTest_CommonCreateState(argv, 0);
+    if (state == NULL) {
+        return 1;
+    }
+
+    /* Parse commandline */
+    if (!SDLTest_CommonDefaultArgs(state, argc, argv)) {
+        return 1;
+    }
 
     if (SDL_Init(SDL_INIT_VIDEO) < 0) {
         SDL_Log("SDL_Init(SDL_INIT_VIDEO) failed: %s", SDL_GetError());
@@ -38,5 +51,6 @@ int main(int argc, char **argv)
     }
 
     SDL_Quit();
+    SDLTest_CommonDestroyState(state);
     return 0;
 }

+ 14 - 0
test/testdisplayinfo.c

@@ -16,6 +16,7 @@
 
 #include <SDL3/SDL.h>
 #include <SDL3/SDL_main.h>
+#include <SDL3/SDL_test.h>
 
 static void
 print_mode(const char *prefix, const SDL_DisplayMode *mode)
@@ -35,10 +36,22 @@ int main(int argc, char *argv[])
     const SDL_DisplayMode **modes;
     const SDL_DisplayMode *mode;
     int num_displays, i;
+    SDLTest_CommonState *state;
+
+    /* Initialize test framework */
+    state = SDLTest_CommonCreateState(argv, 0);
+    if (state == NULL) {
+        return 1;
+    }
 
     /* Enable standard application logging */
     SDL_LogSetPriority(SDL_LOG_CATEGORY_APPLICATION, SDL_LOG_PRIORITY_INFO);
 
+    /* Parse commandline */
+    if (!SDLTest_CommonDefaultArgs(state, argc, argv)) {
+        return 1;
+    }
+
     /* Load the SDL library */
     if (SDL_Init(SDL_INIT_VIDEO) < 0) {
         SDL_LogError(SDL_LOG_CATEGORY_APPLICATION, "Couldn't initialize SDL: %s\n", SDL_GetError());
@@ -85,5 +98,6 @@ int main(int argc, char *argv[])
     SDL_free(displays);
 
     SDL_Quit();
+    SDLTest_CommonDestroyState(state);
     return 0;
 }

+ 15 - 0
test/testdrawchessboard.c

@@ -20,6 +20,7 @@
 
 #include <SDL3/SDL.h>
 #include <SDL3/SDL_main.h>
+#include <SDL3/SDL_test.h>
 
 static SDL_Window *window;
 static SDL_Renderer *renderer;
@@ -101,9 +102,22 @@ static void loop(void)
 
 int main(int argc, char *argv[])
 {
+    SDLTest_CommonState *state;
+
+    /* Initialize test framework */
+    state = SDLTest_CommonCreateState(argv, 0);
+    if (state == NULL) {
+        return 1;
+    }
+
     /* Enable standard application logging */
     SDL_LogSetPriority(SDL_LOG_CATEGORY_APPLICATION, SDL_LOG_PRIORITY_INFO);
 
+    /* Parse commandline */
+    if (!SDLTest_CommonDefaultArgs(state, argc, argv)) {
+        return 1;
+    }
+
     /* Initialize SDL */
     if (SDL_Init(SDL_INIT_VIDEO) != 0) {
         SDL_LogError(SDL_LOG_CATEGORY_APPLICATION, "SDL_Init fail : %s\n", SDL_GetError());
@@ -138,5 +152,6 @@ int main(int argc, char *argv[])
 #endif
 
     SDL_Quit();
+    SDLTest_CommonDestroyState(state);
     return 0;
 }

+ 3 - 3
test/testdropfile.c

@@ -33,15 +33,15 @@ int main(int argc, char *argv[])
     float x = 0.0f, y = 0.0f;
     unsigned int windowID = 0;
 
-    /* Enable standard application logging */
-    SDL_LogSetPriority(SDL_LOG_CATEGORY_APPLICATION, SDL_LOG_PRIORITY_INFO);
-
     /* Initialize test framework */
     state = SDLTest_CommonCreateState(argv, SDL_INIT_VIDEO);
     if (state == NULL) {
         return 1;
     }
 
+    /* Enable standard application logging */
+    SDL_LogSetPriority(SDL_LOG_CATEGORY_APPLICATION, SDL_LOG_PRIORITY_INFO);
+
     for (i = 1; i < argc;) {
         int consumed;
 

+ 14 - 0
test/testerror.c

@@ -16,6 +16,7 @@
 
 #include <SDL3/SDL.h>
 #include <SDL3/SDL_main.h>
+#include <SDL3/SDL_test.h>
 
 static int alive = 0;
 
@@ -44,10 +45,22 @@ ThreadFunc(void *data)
 int main(int argc, char *argv[])
 {
     SDL_Thread *thread;
+    SDLTest_CommonState *state;
+
+    /* Initialize test framework */
+    state = SDLTest_CommonCreateState(argv, 0);
+    if (state == NULL) {
+        return 1;
+    }
 
     /* Enable standard application logging */
     SDL_LogSetPriority(SDL_LOG_CATEGORY_APPLICATION, SDL_LOG_PRIORITY_INFO);
 
+    /* Parse commandline */
+    if (!SDLTest_CommonDefaultArgs(state, argc, argv)) {
+        return 1;
+    }
+
     /* Load the SDL library */
     if (SDL_Init(0) < 0) {
         SDL_LogError(SDL_LOG_CATEGORY_APPLICATION, "Couldn't initialize SDL: %s\n", SDL_GetError());
@@ -77,5 +90,6 @@ int main(int argc, char *argv[])
     SDL_Log("Main thread error string: %s\n", SDL_GetError());
 
     SDL_Quit();
+    SDLTest_CommonDestroyState(state);
     return 0;
 }

+ 19 - 1
test/testevdev.c

@@ -12,6 +12,7 @@
 */
 
 #include "../src/SDL_internal.h"
+#include <SDL3/SDL_test.h>
 
 #include <stdio.h>
 #include <string.h>
@@ -1038,5 +1039,22 @@ run_test(void)
 
 int main(int argc, char *argv[])
 {
-    return run_test() ? 0 : 1;
+    int result;
+    SDLTest_CommonState *state;
+
+    /* Initialize test framework */
+    state = SDLTest_CommonCreateState(argv, 0);
+    if (state == NULL) {
+        return 1;
+    }
+
+    /* Parse commandline */
+    if (!SDLTest_CommonDefaultArgs(state, argc, argv)) {
+        return 1;
+    }
+
+    result = run_test() ? 0 : 1;
+
+    SDLTest_CommonDestroyState(state);
+    return result;
 }

+ 16 - 0
test/testfile.c

@@ -25,6 +25,7 @@
 
 #include <SDL3/SDL.h>
 #include <SDL3/SDL_main.h>
+#include <SDL3/SDL_test.h>
 
 /* WARNING ! those 2 files will be destroyed by this test program */
 
@@ -40,6 +41,8 @@
 #define NULL ((void *)0)
 #endif
 
+static SDLTest_CommonState *state;
+
 static void
 cleanup(void)
 {
@@ -55,6 +58,7 @@ rwops_error_quit(unsigned line, SDL_RWops *rwops)
         rwops->close(rwops); /* This calls SDL_DestroyRW(rwops); */
     }
     cleanup();
+    SDLTest_CommonDestroyState(state);
     exit(1); /* quit with rwops error (test failed) */
 }
 
@@ -65,9 +69,20 @@ int main(int argc, char *argv[])
     SDL_RWops *rwops = NULL;
     char test_buf[30];
 
+    /* Initialize test framework */
+    state = SDLTest_CommonCreateState(argv, 0);
+    if (state == NULL) {
+        return 1;
+    }
+
     /* Enable standard application logging */
     SDL_LogSetPriority(SDL_LOG_CATEGORY_APPLICATION, SDL_LOG_PRIORITY_INFO);
 
+    /* Parse commandline */
+    if (!SDLTest_CommonDefaultArgs(state, argc, argv)) {
+        return 1;
+    }
+
     cleanup();
 
     /* test 1 : basic argument test: all those calls to SDL_RWFromFile should fail */
@@ -354,5 +369,6 @@ int main(int argc, char *argv[])
     rwops->close(rwops);
     SDL_Log("test5 OK\n");
     cleanup();
+    SDLTest_CommonDestroyState(state);
     return 0; /* all ok */
 }

+ 14 - 0
test/testfilesystem.c

@@ -13,15 +13,28 @@
 
 #include <SDL3/SDL.h>
 #include <SDL3/SDL_main.h>
+#include <SDL3/SDL_test.h>
 
 int main(int argc, char *argv[])
 {
+    SDLTest_CommonState *state;
     char *base_path;
     char *pref_path;
 
+    /* Initialize test framework */
+    state = SDLTest_CommonCreateState(argv, 0);
+    if (state == NULL) {
+        return 1;
+    }
+
     /* Enable standard application logging */
     SDL_LogSetPriority(SDL_LOG_CATEGORY_APPLICATION, SDL_LOG_PRIORITY_INFO);
 
+    /* Parse commandline */
+    if (!SDLTest_CommonDefaultArgs(state, argc, argv)) {
+        return 1;
+    }
+
     if (SDL_Init(0) == -1) {
         SDL_LogError(SDL_LOG_CATEGORY_APPLICATION, "SDL_Init() failed: %s\n", SDL_GetError());
         return 1;
@@ -55,5 +68,6 @@ int main(int argc, char *argv[])
     }
 
     SDL_Quit();
+    SDLTest_CommonDestroyState(state);
     return 0;
 }

+ 51 - 23
test/testgamepad.c

@@ -14,6 +14,7 @@
 
 #include <SDL3/SDL.h>
 #include <SDL3/SDL_main.h>
+#include <SDL3/SDL_test.h>
 #include "testutils.h"
 
 #ifdef __EMSCRIPTEN__
@@ -862,7 +863,14 @@ static void loop(void *arg)
 int main(int argc, char *argv[])
 {
     int i;
-    int gamepad_index = 0;
+    int gamepad_index = -1;
+    SDLTest_CommonState *state;
+
+    /* Initialize test framework */
+    state = SDLTest_CommonCreateState(argv, 0);
+    if (state == NULL) {
+        return 1;
+    }
 
     SDL_SetHint(SDL_HINT_ACCELEROMETER_AS_JOYSTICK, "0");
     SDL_SetHint(SDL_HINT_JOYSTICK_HIDAPI_PS4_RUMBLE, "1");
@@ -875,6 +883,47 @@ int main(int argc, char *argv[])
     /* Enable standard application logging */
     SDL_LogSetPriority(SDL_LOG_CATEGORY_APPLICATION, SDL_LOG_PRIORITY_INFO);
 
+    /* Parse commandline */
+    for (i = 1; i < argc;) {
+        int consumed;
+
+        consumed = SDLTest_CommonArg(state, i);
+        if (!consumed) {
+            if (SDL_strcmp(argv[i], "--mappings") == 0) {
+                int map_i;
+                SDL_Log("Supported mappings:\n");
+                for (map_i = 0; map_i < SDL_GetNumGamepadMappings(); ++map_i) {
+                    char *mapping = SDL_GetGamepadMappingForIndex(map_i);
+                    if (mapping) {
+                        SDL_Log("\t%s\n", mapping);
+                        SDL_free(mapping);
+                    }
+                }
+                SDL_Log("\n");
+                consumed = 1;
+            } else if (SDL_strcmp(argv[i], "--virtual") == 0) {
+                OpenVirtualGamepad();
+                consumed = 1;
+            } else if (gamepad_index < 0) {
+                char *endptr = NULL;
+                gamepad_index = (int)SDL_strtol(argv[i], &endptr, 0);
+                if (endptr != argv[i] && *endptr == '\0' && gamepad_index >= 0) {
+                    consumed = 1;
+                }
+            }
+        }
+        if (consumed <= 0) {
+            static const char *options[] = { "[--mappings]", "[--virtual]", "[index]", NULL };
+            SDLTest_CommonLogUsage(state, argv[0], options);
+            return 1;
+        }
+
+        i += consumed;
+    }
+    if (gamepad_index < 0) {
+        gamepad_index = 0;
+    }
+
     /* Initialize SDL (Note: video is required to start event loop) */
     if (SDL_Init(SDL_INIT_VIDEO | SDL_INIT_JOYSTICK | SDL_INIT_GAMEPAD) < 0) {
         SDL_LogError(SDL_LOG_CATEGORY_APPLICATION, "Couldn't initialize SDL: %s\n", SDL_GetError());
@@ -883,19 +932,6 @@ int main(int argc, char *argv[])
 
     SDL_AddGamepadMappingsFromFile("gamecontrollerdb.txt");
 
-    /* Print information about the mappings */
-    if (argv[1] && SDL_strcmp(argv[1], "--mappings") == 0) {
-        SDL_Log("Supported mappings:\n");
-        for (i = 0; i < SDL_GetNumGamepadMappings(); ++i) {
-            char *mapping = SDL_GetGamepadMappingForIndex(i);
-            if (mapping) {
-                SDL_Log("\t%s\n", mapping);
-                SDL_free(mapping);
-            }
-        }
-        SDL_Log("\n");
-    }
-
     /* Create a window to display gamepad state */
     window = SDL_CreateWindow("Gamepad Test", SCREEN_WIDTH, SCREEN_HEIGHT, 0);
     if (window == NULL) {
@@ -935,15 +971,6 @@ int main(int argc, char *argv[])
     /* Process the initial gamepad list */
     loop(NULL);
 
-    for (i = 1; i < argc; ++i) {
-        if (SDL_strcmp(argv[i], "--virtual") == 0) {
-            OpenVirtualGamepad();
-        }
-        if (argv[i] && *argv[i] != '-') {
-            gamepad_index = SDL_atoi(argv[i]);
-            break;
-        }
-    }
     if (gamepad_index < num_gamepads) {
         gamepad = gamepads[gamepad_index];
     } else {
@@ -970,6 +997,7 @@ int main(int argc, char *argv[])
     SDL_DestroyRenderer(screen);
     SDL_DestroyWindow(window);
     SDL_QuitSubSystem(SDL_INIT_VIDEO | SDL_INIT_JOYSTICK | SDL_INIT_GAMEPAD);
+    SDLTest_CommonDestroyState(state);
 
     return 0;
 }

+ 4 - 3
test/testgeometry.c

@@ -168,14 +168,15 @@ int main(int argc, char *argv[])
     Uint64 then, now;
     Uint32 frames;
 
-    /* Enable standard application logging */
-    SDL_LogSetPriority(SDL_LOG_CATEGORY_APPLICATION, SDL_LOG_PRIORITY_INFO);
-
     /* Initialize test framework */
     state = SDLTest_CommonCreateState(argv, SDL_INIT_VIDEO);
     if (state == NULL) {
         return 1;
     }
+
+    /* Enable standard application logging */
+    SDL_LogSetPriority(SDL_LOG_CATEGORY_APPLICATION, SDL_LOG_PRIORITY_INFO);
+
     for (i = 1; i < argc;) {
         int consumed;
 

+ 5 - 4
test/testgl.c

@@ -45,7 +45,7 @@ static int LoadContext(GL_Context *data)
 #else
 #define SDL_PROC(ret, func, params)                                                         \
     do {                                                                                    \
-        data->func = (ret (APIENTRY *) params)SDL_GL_GetProcAddress(#func);                                          \
+        data->func = (ret (APIENTRY *) params)SDL_GL_GetProcAddress(#func);                 \
         if (!data->func) {                                                                  \
             return SDL_SetError("Couldn't load GL function %s: %s", #func, SDL_GetError()); \
         }                                                                                   \
@@ -210,9 +210,6 @@ int main(int argc, char *argv[])
     int interval = 0;
     int ret_interval = 0;
 
-    /* Enable standard application logging */
-    SDL_LogSetPriority(SDL_LOG_CATEGORY_APPLICATION, SDL_LOG_PRIORITY_INFO);
-
     /* Initialize parameters */
     fsaa = 0;
     accel = -1;
@@ -222,6 +219,10 @@ int main(int argc, char *argv[])
     if (state == NULL) {
         return 1;
     }
+
+    /* Enable standard application logging */
+    SDL_LogSetPriority(SDL_LOG_CATEGORY_APPLICATION, SDL_LOG_PRIORITY_INFO);
+
     for (i = 1; i < argc;) {
         int consumed;
 

+ 11 - 5
test/testgles.c

@@ -103,9 +103,6 @@ int main(int argc, char *argv[])
     Uint32 then, now, frames;
     int status;
 
-    /* Enable standard application logging */
-    SDL_LogSetPriority(SDL_LOG_CATEGORY_APPLICATION, SDL_LOG_PRIORITY_INFO);
-
     /* Initialize parameters */
     fsaa = 0;
     accel = 0;
@@ -115,6 +112,10 @@ int main(int argc, char *argv[])
     if (state == NULL) {
         return 1;
     }
+
+    /* Enable standard application logging */
+    SDL_LogSetPriority(SDL_LOG_CATEGORY_APPLICATION, SDL_LOG_PRIORITY_INFO);
+
     for (i = 1; i < argc;) {
         int consumed;
 
@@ -131,8 +132,13 @@ int main(int argc, char *argv[])
                 if (!argv[i]) {
                     consumed = -1;
                 } else {
-                    depth = SDL_atoi(argv[i]);
-                    consumed = 1;
+                    char *endptr = NULL;
+                    depth = (int)SDL_strtol(argv[i], &endptr, 0);
+                    if (endptr != argv[i] && *endptr == '\0') {
+                        consumed = 1;
+                    } else {
+                        consumed = -1;
+                    }
                 }
             } else {
                 consumed = -1;

+ 7 - 2
test/testgles2.c

@@ -651,8 +651,13 @@ int main(int argc, char *argv[])
                 if (!argv[i]) {
                     consumed = -1;
                 } else {
-                    depth = SDL_atoi(argv[i]);
-                    consumed = 1;
+                    char *endptr = NULL;
+                    depth = (int)SDL_strtol(argv[i], &endptr, 0);
+                    if (endptr != argv[i] && *endptr == '\0') {
+                        consumed = 1;
+                    } else {
+                        consumed = -1;
+                    }
                 }
             } else {
                 consumed = -1;

+ 7 - 2
test/testgles2_sdf.c

@@ -465,8 +465,13 @@ int main(int argc, char *argv[])
                 if (!argv[i]) {
                     consumed = -1;
                 } else {
-                    depth = SDL_atoi(argv[i]);
-                    consumed = 1;
+                    char *endptr = NULL;
+                    depth = (int)SDL_strtol(argv[i], &endptr, 0);
+                    if (endptr != argv[i] && *endptr == '\0') {
+                        consumed = 1;
+                    } else {
+                        consumed = -1;
+                    }
                 }
             } else {
                 consumed = -1;

+ 36 - 17
test/testhaptic.c

@@ -13,10 +13,12 @@ THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
 
 #include <SDL3/SDL.h>
 #include <SDL3/SDL_main.h>
+#include <SDL3/SDL_test.h>
 
 #include <stdlib.h>
 
 static SDL_Haptic *haptic;
+static SDLTest_CommonState *state;
 
 /*
  * prototypes
@@ -32,33 +34,48 @@ static void HapticPrintSupported(SDL_Haptic *);
 int main(int argc, char **argv)
 {
     int i;
-    char *name;
-    int index;
+    char *name = NULL;
+    int index = -1;
     SDL_HapticEffect efx[9];
     int id[9];
     int nefx;
     unsigned int supported;
 
+    /* Initialize test framework */
+    state = SDLTest_CommonCreateState(argv, 0);
+    if (state == NULL) {
+        return 1;
+    }
+
     /* Enable standard application logging */
     SDL_LogSetPriority(SDL_LOG_CATEGORY_APPLICATION, SDL_LOG_PRIORITY_INFO);
+    /* Parse commandline */
+    for (i = 1; i < argc;) {
+        int consumed;
 
-    name = NULL;
-    index = -1;
-    if (argc > 1) {
-        name = argv[1];
-        if ((SDL_strcmp(name, "--help") == 0) || (SDL_strcmp(name, "-h") == 0)) {
-            SDL_Log("USAGE: %s [device]\n"
-                    "If device is a two-digit number it'll use it as an index, otherwise\n"
-                    "it'll use it as if it were part of the device's name.\n",
-                    argv[0]);
-            return 0;
+        consumed = SDLTest_CommonArg(state, i);
+        if (!consumed) {
+            if (!name && index < 0) {
+                size_t len;
+                name = argv[i];
+                len = SDL_strlen(name);
+                if (len < 3 && SDL_isdigit(name[0]) && (len == 1 || SDL_isdigit(name[1]))) {
+                    index = SDL_atoi(name);
+                    name = NULL;
+                }
+                consumed = 1;
+            }
         }
-
-        i = (int)SDL_strlen(name);
-        if ((i < 3) && SDL_isdigit(name[0]) && ((i == 1) || SDL_isdigit(name[1]))) {
-            index = SDL_atoi(name);
-            name = NULL;
+        if (consumed <= 0) {
+            static const char *options[] = { "[device]", NULL };
+            SDLTest_CommonLogUsage(state, argv[0], options);
+            SDL_Log("\n");
+            SDL_Log("If device is a two-digit number it'll use it as an index, otherwise\n"
+                    "it'll use it as if it were part of the device's name.\n");
+            return 1;
         }
+
+        i += consumed;
     }
 
     /* Initialize the force feedbackness */
@@ -281,6 +298,7 @@ int main(int argc, char **argv)
         SDL_HapticClose(haptic);
     }
     SDL_Quit();
+    SDLTest_CommonDestroyState(state);
 
     return 0;
 }
@@ -295,6 +313,7 @@ abort_execution(void)
 
     SDL_HapticClose(haptic);
     SDL_Quit();
+    SDLTest_CommonDestroyState(state);
 
     exit(1);
 }

+ 29 - 3
test/testhotplug.c

@@ -16,6 +16,7 @@
 
 #include <SDL3/SDL.h>
 #include <SDL3/SDL_main.h>
+#include <SDL3/SDL_test.h>
 
 int main(int argc, char *argv[])
 {
@@ -27,11 +28,35 @@ int main(int argc, char *argv[])
     int i;
     SDL_bool enable_haptic = SDL_TRUE;
     Uint32 init_subsystems = SDL_INIT_VIDEO | SDL_INIT_JOYSTICK;
+    SDLTest_CommonState *state;
 
-    for (i = 1; i < argc; ++i) {
-        if (SDL_strcasecmp(argv[i], "--nohaptic") == 0) {
-            enable_haptic = SDL_FALSE;
+    /* Initialize test framework */
+    state = SDLTest_CommonCreateState(argv, 0);
+    if (state == NULL) {
+        return 1;
+    }
+
+    /* Enable standard application logging */
+    SDL_LogSetPriority(SDL_LOG_CATEGORY_APPLICATION, SDL_LOG_PRIORITY_INFO);
+
+    /* Parse commandline */
+    for (i = 1; i < argc;) {
+        int consumed;
+
+        consumed = SDLTest_CommonArg(state, i);
+        if (!consumed) {
+            if (SDL_strcasecmp(argv[i], "--nohaptic") == 0) {
+                enable_haptic = SDL_FALSE;
+                consumed = 1;
+            }
         }
+        if (consumed <= 0) {
+            static const char *options[] = { "[--nohaptic]", NULL };
+            SDLTest_CommonLogUsage(state, argv[0], options);
+            exit(1);
+        }
+
+        i += consumed;
     }
 
     if (enable_haptic) {
@@ -132,6 +157,7 @@ int main(int argc, char *argv[])
     }
 
     SDL_Quit();
+    SDLTest_CommonDestroyState(state);
 
     return 0;
 }

+ 31 - 2
test/testiconv.c

@@ -19,6 +19,7 @@
 
 #include <SDL3/SDL.h>
 #include <SDL3/SDL_main.h>
+#include <SDL3/SDL_test.h>
 #include "testutils.h"
 
 static size_t
@@ -49,18 +50,45 @@ int main(int argc, char *argv[])
         "UCS-4",
     };
 
-    char *fname;
+    char *fname = NULL;
     char buffer[BUFSIZ];
     char *ucs4;
     char *test[2];
     int i;
     FILE *file;
     int errors = 0;
+    SDLTest_CommonState *state;
+
+    /* Initialize test framework */
+    state = SDLTest_CommonCreateState(argv, 0);
+    if (state == NULL) {
+        return 1;
+    }
 
     /* Enable standard application logging */
     SDL_LogSetPriority(SDL_LOG_CATEGORY_APPLICATION, SDL_LOG_PRIORITY_INFO);
 
-    fname = GetResourceFilename(argc > 1 ? argv[1] : NULL, "utf8.txt");
+    /* Parse commandline */
+    for (i = 1; i < argc;) {
+        int consumed;
+
+        consumed = SDLTest_CommonArg(state, i);
+        if (!consumed) {
+            if (!fname) {
+                fname = argv[i];
+                consumed = 1;
+            }
+        }
+        if (consumed <= 0) {
+            static const char *options[] = { "[utf8.txt]", NULL };
+            SDLTest_CommonLogUsage(state, argv[0], options);
+            return 1;
+        }
+
+        i += consumed;
+    }
+
+    fname = GetResourceFilename(fname, "utf8.txt");
     file = fopen(fname, "rb");
     if (file == NULL) {
         SDL_LogError(SDL_LOG_CATEGORY_APPLICATION, "Unable to open %s\n", fname);
@@ -93,5 +121,6 @@ int main(int argc, char *argv[])
     (void)fclose(file);
 
     SDL_LogInfo(SDL_LOG_CATEGORY_APPLICATION, "Total errors: %d\n", errors);
+    SDLTest_CommonDestroyState(state);
     return errors ? errors + 1 : 0;
 }

+ 22 - 25
test/testime.c

@@ -445,11 +445,6 @@ static Uint32 utf8_decode(char *p, size_t len)
     return codepoint;
 }
 
-static void usage(void)
-{
-    SDL_Log("usage: testime [--font fontfile]\n");
-}
-
 static void InitInput(void)
 {
     /* Prepare a rect for text input */
@@ -647,42 +642,43 @@ int main(int argc, char *argv[])
 {
     int i, done;
     SDL_Event event;
-    const char *fontname = DEFAULT_FONT;
-
-    /* Enable standard application logging */
-    SDL_LogSetPriority(SDL_LOG_CATEGORY_APPLICATION, SDL_LOG_PRIORITY_INFO);
+    char *fontname = NULL;
 
     /* Initialize test framework */
     state = SDLTest_CommonCreateState(argv, SDL_INIT_VIDEO);
     if (state == NULL) {
         return 1;
     }
-    for (i = 1; i < argc; i++) {
-        SDLTest_CommonArg(state, i);
-    }
-    for (argc--, argv++; argc > 0; argc--, argv++) {
-        if (SDL_strcmp(argv[0], "--help") == 0) {
-            usage();
-            return 0;
-        }
 
-        else if (SDL_strcmp(argv[0], "--font") == 0) {
-            argc--;
-            argv++;
+    /* Enable standard application logging */
+    SDL_LogSetPriority(SDL_LOG_CATEGORY_APPLICATION, SDL_LOG_PRIORITY_INFO);
 
-            if (argc > 0) {
-                fontname = argv[0];
-            } else {
-                usage();
-                return 0;
+    /* Parse commandline */
+    for (i = 1; i < argc;) {
+        int consumed;
+
+        consumed = SDLTest_CommonArg(state, i);
+        if (SDL_strcmp(argv[i], "--font") == 0) {
+            if (*argv[i+1]) {
+                fontname = argv[i+1];
+                consumed = 2;
             }
         }
+        if (consumed <= 0) {
+            static const char *options[] = { "[--font fontfile]", NULL };
+            SDLTest_CommonLogUsage(state, argv[0], options);
+            return 1;
+        }
+
+        i += consumed;
     }
 
     if (!SDLTest_CommonInit(state)) {
         return 2;
     }
 
+    fontname = GetResourceFilename(fontname, DEFAULT_FONT);
+
 #ifdef HAVE_SDL_TTF
     /* Initialize fonts */
     TTF_Init();
@@ -794,6 +790,7 @@ int main(int argc, char *argv[])
             }
         }
     }
+    SDL_free(fontname);
     CleanupVideo();
     SDLTest_CommonQuit(state);
     return 0;

+ 23 - 5
test/testjoystick.c

@@ -16,6 +16,7 @@
 
 #include <SDL3/SDL.h>
 #include <SDL3/SDL_main.h>
+#include <SDL3/SDL_test.h>
 
 #ifdef __EMSCRIPTEN__
 #include <emscripten/emscripten.h>
@@ -32,7 +33,6 @@
 static SDL_Window *window = NULL;
 static SDL_Renderer *screen = NULL;
 static SDL_Joystick *joystick = NULL;
-static SDL_bool done = SDL_FALSE;
 
 static void
 PrintJoystick(SDL_Joystick *joy)
@@ -103,6 +103,7 @@ static void loop(void *arg)
 {
     SDL_Event event;
     int i;
+    SDL_bool *done = (SDL_bool*)arg;
 
     /* blank screen, set up for drawing this frame. */
     SDL_SetRenderDrawColor(screen, 0x0, 0x0, 0x0, SDL_ALPHA_OPAQUE);
@@ -200,7 +201,7 @@ static void loop(void *arg)
         case SDL_EVENT_FINGER_DOWN:
         case SDL_EVENT_MOUSE_BUTTON_DOWN:
         case SDL_EVENT_QUIT:
-            done = SDL_TRUE;
+            *done = SDL_TRUE;
             break;
         default:
             break;
@@ -279,7 +280,7 @@ static void loop(void *arg)
     SDL_RenderPresent(screen);
 
 #ifdef __EMSCRIPTEN__
-    if (done) {
+    if (*done == SDL_TRUE) {
         emscripten_cancel_main_loop();
     }
 #endif
@@ -287,11 +288,25 @@ static void loop(void *arg)
 
 int main(int argc, char *argv[])
 {
+    SDL_bool done;
+    SDLTest_CommonState *state;
+
+    /* Initialize test framework */
+    state = SDLTest_CommonCreateState(argv, 0);
+    if (state == NULL) {
+        return 1;
+    }
+
     SDL_SetHint(SDL_HINT_ACCELEROMETER_AS_JOYSTICK, "0");
 
     /* Enable standard application logging */
     SDL_LogSetPriority(SDL_LOG_CATEGORY_APPLICATION, SDL_LOG_PRIORITY_INFO);
 
+    /* Parse commandline */
+    if (!SDLTest_CommonDefaultArgs(state, argc, argv)) {
+        return 1;
+    }
+
     /* Initialize SDL (Note: video is required to start event loop) */
     if (SDL_Init(SDL_INIT_VIDEO | SDL_INIT_JOYSTICK) < 0) {
         SDL_LogError(SDL_LOG_CATEGORY_APPLICATION, "Couldn't initialize SDL: %s\n", SDL_GetError());
@@ -316,12 +331,14 @@ int main(int argc, char *argv[])
     SDL_RenderClear(screen);
     SDL_RenderPresent(screen);
 
+    done = SDL_FALSE;
+
     /* Loop, getting joystick events! */
 #ifdef __EMSCRIPTEN__
-    emscripten_set_main_loop_arg(loop, NULL, 0, 1);
+    emscripten_set_main_loop_arg(loop, &done, 0, 1);
 #else
     while (!done) {
-        loop(NULL);
+        loop(&done);
     }
 #endif
 
@@ -329,6 +346,7 @@ int main(int argc, char *argv[])
     SDL_DestroyWindow(window);
 
     SDL_QuitSubSystem(SDL_INIT_VIDEO | SDL_INIT_JOYSTICK);
+    SDLTest_CommonDestroyState(state);
 
     return 0;
 }

+ 14 - 0
test/testkeys.c

@@ -16,14 +16,27 @@
 
 #include <SDL3/SDL.h>
 #include <SDL3/SDL_main.h>
+#include <SDL3/SDL_test.h>
 
 int main(int argc, char *argv[])
 {
     SDL_Scancode scancode;
+    SDLTest_CommonState *state;
+
+    /* Initialize test framework */
+    state = SDLTest_CommonCreateState(argv, 0);
+    if (state == NULL) {
+        return 1;
+    }
 
     /* Enable standard application logging */
     SDL_LogSetPriority(SDL_LOG_CATEGORY_APPLICATION, SDL_LOG_PRIORITY_INFO);
 
+    /* Parse commandline */
+    if (!SDLTest_CommonDefaultArgs(state, argc, argv)) {
+        return 1;
+    }
+
     if (SDL_Init(SDL_INIT_VIDEO) < 0) {
         SDL_LogError(SDL_LOG_CATEGORY_APPLICATION, "Couldn't initialize SDL: %s\n", SDL_GetError());
         exit(1);
@@ -33,5 +46,6 @@ int main(int argc, char *argv[])
                 SDL_GetScancodeName(scancode));
     }
     SDL_Quit();
+    SDLTest_CommonDestroyState(state);
     return 0;
 }

+ 50 - 13
test/testloadso.c

@@ -17,22 +17,67 @@
 
 #include <SDL3/SDL.h>
 #include <SDL3/SDL_main.h>
+#include <SDL3/SDL_test.h>
 
 typedef int (*fntype)(const char *);
 
+static void log_usage(char *progname, SDLTest_CommonState *state) {
+    static const char *options[] = { "library", "functionname|--hello", NULL };
+    SDLTest_CommonLogUsage(state, progname, options);
+    SDL_Log("USAGE: %s <library> <functionname>\n", progname);
+    SDL_Log("       %s <lib with puts()> --hello\n", progname);
+}
+
 int main(int argc, char *argv[])
 {
+    int i;
     int retval = 0;
     int hello = 0;
     const char *libname = NULL;
     const char *symname = NULL;
     void *lib = NULL;
     fntype fn = NULL;
+    SDLTest_CommonState *state;
+
+    /* Initialize test framework */
+    state = SDLTest_CommonCreateState(argv, 0);
+    if (state == NULL) {
+        return 1;
+    }
+
+    /* Enable standard application logging */
+    SDL_LogSetPriority(SDL_LOG_CATEGORY_APPLICATION, SDL_LOG_PRIORITY_INFO);
+
+    /* Parse commandline */
+    for (i = 1; i < argc;) {
+        int consumed;
+
+        consumed = SDLTest_CommonArg(state, i);
+        if (!consumed) {
+            if (SDL_strcmp(argv[i], "--hello") == 0) {
+                if (!symname || SDL_strcmp(symname, "puts") == 0) {
+                    symname = "puts";
+                    consumed = 1;
+                    hello = 1;
+                }
+            } else if (!libname) {
+                libname = argv[i];
+                consumed = 1;
+            } else if (!symname) {
+                symname = argv[i];
+                consumed = 1;
+            }
+        }
+        if (consumed <= 0) {
+            log_usage(argv[0], state);
+            return 1;
+        }
+
+        i += consumed;
+    }
 
-    if (argc != 3) {
-        const char *app = argv[0];
-        SDL_Log("USAGE: %s <library> <functionname>\n", app);
-        SDL_Log("       %s --hello <lib with puts()>\n", app);
+    if (!libname || !symname) {
+        log_usage(argv[0], state);
         return 1;
     }
 
@@ -42,15 +87,6 @@ int main(int argc, char *argv[])
         return 2;
     }
 
-    if (SDL_strcmp(argv[1], "--hello") == 0) {
-        hello = 1;
-        libname = argv[2];
-        symname = "puts";
-    } else {
-        libname = argv[1];
-        symname = argv[2];
-    }
-
     lib = SDL_LoadObject(libname);
     if (lib == NULL) {
         SDL_LogError(SDL_LOG_CATEGORY_APPLICATION, "SDL_LoadObject('%s') failed: %s\n",
@@ -74,5 +110,6 @@ int main(int argc, char *argv[])
         SDL_UnloadObject(lib);
     }
     SDL_Quit();
+    SDLTest_CommonDestroyState(state);
     return retval;
 }

+ 56 - 19
test/testlocale.c

@@ -11,8 +11,7 @@
 */
 #include <SDL3/SDL.h>
 #include <SDL3/SDL_main.h>
-
-/* !!! FIXME: move this to the test framework */
+#include <SDL3/SDL_test.h>
 
 static void log_locales(void)
 {
@@ -35,31 +34,69 @@ static void log_locales(void)
 
 int main(int argc, char **argv)
 {
+    int i;
+    int listen = 0;
+    SDLTest_CommonState *state;
+
+    /* Initialize test framework */
+    state = SDLTest_CommonCreateState(argv, SDL_INIT_VIDEO);
+    if (state == NULL) {
+        return 1;
+    }
+
     /* Enable standard application logging */
     SDL_LogSetPriority(SDL_LOG_CATEGORY_APPLICATION, SDL_LOG_PRIORITY_INFO);
 
+    /* Parse commandline */
+    for (i = 1; i < argc;) {
+        int consumed;
+
+        consumed = SDLTest_CommonArg(state, i);
+        if (!consumed) {
+            if (SDL_strcmp(argv[1], "--listen") == 0) {
+                listen = 1;
+                consumed = 1;
+            }
+        }
+        if (consumed <= 0) {
+            static const char *options[] = { "[--listen]", NULL };
+            SDLTest_CommonLogUsage(state, argv[0], options);
+            return 1;
+        }
+
+        i += consumed;
+    }
+
     /* Print locales and languages */
-    if (SDL_Init(SDL_INIT_VIDEO) != -1) {
-        log_locales();
-
-        if ((argc == 2) && (SDL_strcmp(argv[1], "--listen") == 0)) {
-            SDL_bool keep_going = SDL_TRUE;
-            while (keep_going) {
-                SDL_Event e;
-                while (SDL_PollEvent(&e)) {
-                    if (e.type == SDL_EVENT_QUIT) {
-                        keep_going = SDL_FALSE;
-                    } else if (e.type == SDL_EVENT_LOCALE_CHANGED) {
-                        SDL_Log("Saw SDL_EVENT_LOCALE_CHANGED event!");
-                        log_locales();
-                    }
+    if (SDLTest_CommonInit(state) == SDL_FALSE) {
+        return 1;
+    }
+
+    log_locales();
+
+    if (listen) {
+        int done = 0;
+        while (!done) {
+            SDL_Event e;
+            SDLTest_CommonEvent(state, &e, &done);
+            while (SDL_PollEvent(&e)) {
+                if (e.type == SDL_EVENT_QUIT) {
+                    done = 1;
+                } else if (e.type == SDL_EVENT_LOCALE_CHANGED) {
+                    SDL_Log("Saw SDL_EVENT_LOCALE_CHANGED event!");
+                    log_locales();
                 }
-                SDL_Delay(10);
             }
-        }
 
-        SDL_Quit();
+            for (i = 0; i < state->num_windows; i++) {
+                SDL_RenderPresent(state->renderers[i]);
+            }
+
+            SDL_Delay(10);
+        }
     }
 
+    SDLTest_CommonQuit(state);
+
     return 0;
 }

+ 14 - 0
test/testmessage.c

@@ -16,6 +16,7 @@
 
 #include <SDL3/SDL.h>
 #include <SDL3/SDL_main.h>
+#include <SDL3/SDL_test.h>
 
 /* Call this instead of exit(), so we can clean up SDL: atexit() is evil. */
 static void
@@ -81,10 +82,22 @@ button_messagebox(void *eventNumber)
 int main(int argc, char *argv[])
 {
     int success;
+    SDLTest_CommonState *state;
+
+    /* Initialize test framework */
+    state = SDLTest_CommonCreateState(argv, 0);
+    if (state == NULL) {
+        return 1;
+    }
 
     /* Enable standard application logging */
     SDL_LogSetPriority(SDL_LOG_CATEGORY_APPLICATION, SDL_LOG_PRIORITY_INFO);
 
+    /* Parse commandline */
+    if (!SDLTest_CommonDefaultArgs(state, argc, argv)) {
+        return 1;
+    }
+
     success = SDL_ShowSimpleMessageBox(SDL_MESSAGEBOX_ERROR,
                                        "Simple MessageBox",
                                        "This is a simple error MessageBox",
@@ -208,5 +221,6 @@ int main(int argc, char *argv[])
     }
 
     SDL_Quit();
+    SDLTest_CommonDestroyState(state);
     return 0;
 }

+ 34 - 14
test/testmouse.c

@@ -12,6 +12,7 @@
 
 #include <SDL3/SDL.h>
 #include <SDL3/SDL_main.h>
+#include <SDL3/SDL_test.h>
 
 #ifdef __EMSCRIPTEN__
 #include <emscripten/emscripten.h>
@@ -49,7 +50,10 @@ static SDL_bool wheel_y_active = SDL_FALSE;
 static float wheel_x = SCREEN_WIDTH * 0.5f;
 static float wheel_y = SCREEN_HEIGHT * 0.5f;
 
-static SDL_bool done = SDL_FALSE;
+struct mouse_loop_data {
+    SDL_bool done;
+    SDL_Renderer *renderer;
+};
 
 static void DrawObject(SDL_Renderer *renderer, Object *object)
 {
@@ -104,8 +108,9 @@ static void AppendObject(Object *object)
 
 static void loop(void *arg)
 {
-    SDL_Renderer *renderer = (SDL_Renderer *)arg;
+    struct mouse_loop_data *loop_data = (struct mouse_loop_data *)arg;
     SDL_Event event;
+    SDL_Renderer *renderer = loop_data->renderer;
 
     /* Check for events */
     while (SDL_PollEvent(&event)) {
@@ -212,7 +217,7 @@ static void loop(void *arg)
             break;
 
         case SDL_EVENT_QUIT:
-            done = SDL_TRUE;
+            loop_data->done = SDL_TRUE;
             break;
 
         default:
@@ -241,7 +246,7 @@ static void loop(void *arg)
     SDL_RenderPresent(renderer);
 
 #ifdef __EMSCRIPTEN__
-    if (done) {
+    if (loop_data->done) {
         emscripten_cancel_main_loop();
     }
 #endif
@@ -249,11 +254,23 @@ static void loop(void *arg)
 
 int main(int argc, char *argv[])
 {
-    SDL_Renderer *renderer;
+    struct mouse_loop_data loop_data;
+    SDLTest_CommonState *state;
+
+    /* Initialize test framework */
+    state = SDLTest_CommonCreateState(argv, 0);
+    if (state == NULL) {
+        return 1;
+    }
 
     /* Enable standard application logging */
     SDL_LogSetPriority(SDL_LOG_CATEGORY_APPLICATION, SDL_LOG_PRIORITY_INFO);
 
+    /* Parse commandline */
+    if (!SDLTest_CommonDefaultArgs(state, argc, argv)) {
+        return 1;
+    }
+
     /* Initialize SDL (Note: video is required to start event loop) */
     if (SDL_Init(SDL_INIT_VIDEO) < 0) {
         SDL_LogError(SDL_LOG_CATEGORY_APPLICATION, "Couldn't initialize SDL: %s\n", SDL_GetError());
@@ -262,31 +279,34 @@ int main(int argc, char *argv[])
 
     /* Create a window to display joystick axis position */
     window = SDL_CreateWindow("Mouse Test", SCREEN_WIDTH, SCREEN_HEIGHT, 0);
-    if (window == NULL) {
+    if (!window) {
         SDL_LogError(SDL_LOG_CATEGORY_APPLICATION, "Couldn't create window: %s\n", SDL_GetError());
-        return SDL_FALSE;
+        return 0;
     }
 
-    renderer = SDL_CreateRenderer(window, NULL, 0);
-    if (renderer == NULL) {
+    loop_data.done = SDL_FALSE;
+
+    loop_data.renderer = SDL_CreateRenderer(window, NULL, 0);
+    if (!loop_data.renderer) {
         SDL_LogError(SDL_LOG_CATEGORY_APPLICATION, "Couldn't create renderer: %s\n", SDL_GetError());
         SDL_DestroyWindow(window);
-        return SDL_FALSE;
+        return 0;
     }
 
     /* Main render loop */
 #ifdef __EMSCRIPTEN__
-    emscripten_set_main_loop_arg(loop, renderer, 0, 1);
+    emscripten_set_main_loop_arg(loop, &loop_data, 0, 1);
 #else
-    while (!done) {
-        loop(renderer);
+    while (loop_data.done == SDL_FALSE) {
+        loop(&loop_data);
     }
 #endif
 
-    SDL_DestroyRenderer(renderer);
+    SDL_DestroyRenderer(loop_data.renderer);
     SDL_DestroyWindow(window);
 
     SDL_Quit();
+    SDLTest_CommonDestroyState(state);
 
     return 0;
 }

+ 40 - 6
test/testmultiaudio.c

@@ -11,6 +11,9 @@
 */
 #include <SDL3/SDL.h>
 #include <SDL3/SDL_main.h>
+#include <SDL3/SDL_test.h>
+
+#include "testutils.h"
 
 #include <stdio.h> /* for fflush() and stdout */
 
@@ -166,10 +169,39 @@ test_multi_audio(int devcount)
 int main(int argc, char **argv)
 {
     int devcount = 0;
+    int i;
+    char *filename = NULL;
+    SDLTest_CommonState *state;
+
+    /* Initialize test framework */
+    state = SDLTest_CommonCreateState(argv, 0);
+    if (state == NULL) {
+        return 1;
+    }
 
     /* Enable standard application logging */
     SDL_LogSetPriority(SDL_LOG_CATEGORY_APPLICATION, SDL_LOG_PRIORITY_INFO);
 
+    /* Parse commandline */
+    for (i = 1; i < argc;) {
+        int consumed;
+
+        consumed = SDLTest_CommonArg(state, i);
+        if (!consumed) {
+            if (!filename) {
+                filename = argv[i];
+                consumed = 1;
+            }
+        }
+        if (consumed <= 0) {
+            static const char *options[] = { "[sample.wav]", NULL };
+            SDLTest_CommonLogUsage(state, argv[0], options);
+            return 1;
+        }
+
+        i += consumed;
+    }
+
     /* Load the SDL library */
     if (SDL_Init(SDL_INIT_AUDIO) < 0) {
         SDL_LogError(SDL_LOG_CATEGORY_APPLICATION, "Couldn't initialize SDL: %s\n", SDL_GetError());
@@ -178,24 +210,26 @@ int main(int argc, char **argv)
 
     SDL_Log("Using audio driver: %s\n", SDL_GetCurrentAudioDriver());
 
+    filename = GetResourceFilename(filename, "sample.wav");
+
     devcount = SDL_GetNumAudioDevices(0);
     if (devcount < 1) {
         SDL_LogError(SDL_LOG_CATEGORY_APPLICATION, "Don't see any specific audio devices!\n");
     } else {
-        char *file = GetResourceFilename(argc > 1 ? argv[1] : NULL, "sample.wav");
-
         /* Load the wave file into memory */
-        if (SDL_LoadWAV(file, &spec, &sound, &soundlen) == NULL) {
-            SDL_LogError(SDL_LOG_CATEGORY_APPLICATION, "Couldn't load %s: %s\n", file,
+        if (SDL_LoadWAV(filename, &spec, &sound, &soundlen) == NULL) {
+            SDL_LogError(SDL_LOG_CATEGORY_APPLICATION, "Couldn't load %s: %s\n", filename,
                          SDL_GetError());
         } else {
             test_multi_audio(devcount);
             SDL_free(sound);
         }
-
-        SDL_free(file);
     }
 
+    SDL_free(filename);
+
     SDL_Quit();
+    SDLTest_CommonDestroyState(state);
+
     return 0;
 }

+ 14 - 0
test/testnative.c

@@ -18,6 +18,7 @@
 #include "testutils.h"
 
 #include <SDL3/SDL_main.h>
+#include <SDL3/SDL_test.h>
 
 #define WINDOW_W    640
 #define WINDOW_H    480
@@ -39,6 +40,7 @@ static NativeWindowFactory *factories[] = {
 static NativeWindowFactory *factory = NULL;
 static void *native_window;
 static SDL_FRect *positions, *velocities;
+static SDLTest_CommonState *state;
 
 /* Call this instead of exit(), so we can clean up SDL: atexit() is evil. */
 static void
@@ -48,6 +50,7 @@ quit(int rc)
     if (native_window != NULL && factory != NULL) {
         factory->DestroyNativeWindow(native_window);
     }
+    SDLTest_CommonDestroyState(state);
     exit(rc);
 }
 
@@ -100,9 +103,20 @@ int main(int argc, char *argv[])
     int sprite_w, sprite_h;
     SDL_Event event;
 
+    /* Initialize test framework */
+    state = SDLTest_CommonCreateState(argv, 0);
+    if (state == NULL) {
+        return 1;
+    }
+
     /* Enable standard application logging */
     SDL_LogSetPriority(SDL_LOG_CATEGORY_APPLICATION, SDL_LOG_PRIORITY_INFO);
 
+    /* Parse commandline */
+    if (!SDLTest_CommonDefaultArgs(state, argc, argv)) {
+        return 1;
+    }
+
     if (SDL_Init(SDL_INIT_VIDEO) < 0) {
         SDL_LogError(SDL_LOG_CATEGORY_APPLICATION, "Couldn't initialize SDL video: %s\n",
                      SDL_GetError());

+ 8 - 0
test/testnative.h

@@ -15,6 +15,14 @@
 */
 #include <SDL3/SDL.h>
 
+/* Hack to avoid dynapi renaming */
+#include "../src/dynapi/SDL_dynapi.h"
+#ifdef SDL_DYNAMIC_API
+#undef SDL_DYNAMIC_API
+#endif
+
+#include "../src/SDL_internal.h"
+
 typedef struct
 {
     const char *tag;

+ 14 - 0
test/testoffscreen.c

@@ -21,6 +21,7 @@
 
 #include <SDL3/SDL.h>
 #include <SDL3/SDL_main.h>
+#include <SDL3/SDL_test.h>
 #include <SDL3/SDL_opengl.h>
 
 static SDL_Renderer *renderer = NULL;
@@ -97,10 +98,22 @@ int main(int argc, char *argv[])
     Uint64 then, now;
     Uint32 frames;
 #endif
+    SDLTest_CommonState *state;
+
+    /* Initialize test framework */
+    state = SDLTest_CommonCreateState(argv, 0);
+    if (state == NULL) {
+        return 1;
+    }
 
     /* Enable standard application logging */
     SDL_LogSetPriority(SDL_LOG_CATEGORY_APPLICATION, SDL_LOG_PRIORITY_INFO);
 
+    /* Parse commandline */
+    if (!SDLTest_CommonDefaultArgs(state, argc, argv)) {
+        return 1;
+    }
+
     /* Force the offscreen renderer, if it cannot be created then fail out */
     SDL_SetHint("SDL_VIDEO_DRIVER", "offscreen");
     if (SDL_InitSubSystem(SDL_INIT_VIDEO) < 0) {
@@ -159,6 +172,7 @@ int main(int argc, char *argv[])
     SDL_DestroyRenderer(renderer);
     SDL_DestroyWindow(window);
     SDL_Quit();
+    SDLTest_CommonDestroyState(state);
 
     return 0;
 }

+ 30 - 2
test/testplatform.c

@@ -11,6 +11,7 @@
 */
 #include <SDL3/SDL.h>
 #include <SDL3/SDL_main.h>
+#include <SDL3/SDL_test.h>
 
 /*
  * Watcom C flags these as Warning 201: "Unreachable code" if you just
@@ -440,15 +441,40 @@ static int TestAssertions(SDL_bool verbose)
 
 int main(int argc, char *argv[])
 {
+    int i;
     SDL_bool verbose = SDL_TRUE;
     int status = 0;
+    SDLTest_CommonState *state;
+
+    /* Initialize test framework */
+    state = SDLTest_CommonCreateState(argv, 0);
+    if (state == NULL) {
+        return 1;
+    }
 
     /* Enable standard application logging */
     SDL_LogSetPriority(SDL_LOG_CATEGORY_APPLICATION, SDL_LOG_PRIORITY_INFO);
 
-    if (argv[1] && (SDL_strcmp(argv[1], "-q") == 0)) {
-        verbose = SDL_FALSE;
+    /* Parse commandline */
+    for (i = 1; i < argc;) {
+        int consumed;
+
+        consumed = SDLTest_CommonArg(state, i);
+        if (!consumed) {
+            if (SDL_strcmp(argv[i], "-q") == 0) {
+                verbose = SDL_FALSE;
+                consumed = 1;
+            }
+        }
+        if (consumed <= 0) {
+            static const char *options[] = { "[-q]", NULL };
+            SDLTest_CommonLogUsage(state, argv[0], options);
+            return 1;
+        }
+
+        i += consumed;
     }
+
     if (verbose) {
         SDL_Log("This system is running %s\n", SDL_GetPlatform());
     }
@@ -459,5 +485,7 @@ int main(int argc, char *argv[])
     status += TestCPUInfo(verbose);
     status += TestAssertions(verbose);
 
+    SDLTest_CommonDestroyState(state);
+
     return status;
 }

+ 8 - 0
test/testpopup.c

@@ -241,6 +241,14 @@ int main(int argc, char *argv[])
         return 1;
     }
 
+    /* Enable standard application logging */
+    SDL_LogSetPriority(SDL_LOG_CATEGORY_APPLICATION, SDL_LOG_PRIORITY_INFO);
+
+    /* Parse commandline */
+    if (!SDLTest_CommonDefaultArgs(state, argc, argv)) {
+        return 1;
+    }
+
     if (!SDLTest_CommonInit(state)) {
         SDLTest_CommonQuit(state);
         quit(2);

+ 17 - 1
test/testpower.c

@@ -13,6 +13,7 @@
 
 #include <SDL3/SDL.h>
 #include <SDL3/SDL_main.h>
+#include <SDL3/SDL_test.h>
 
 static void
 report_power(void)
@@ -60,10 +61,23 @@ report_power(void)
 
 int main(int argc, char *argv[])
 {
+    SDLTest_CommonState *state;
+
+    /* Initialize test framework */
+    state = SDLTest_CommonCreateState(argv, 0);
+    if (state == NULL) {
+        return 1;
+    }
+
     /* Enable standard application logging */
     SDL_LogSetPriority(SDL_LOG_CATEGORY_APPLICATION, SDL_LOG_PRIORITY_INFO);
 
-    if (SDL_Init(0) == -1) {
+    /* Parse commandline */
+    if (!SDLTest_CommonDefaultArgs(state, argc, argv)) {
+        return 1;
+    }
+
+    if (SDL_Init(0) < 0) {
         SDL_LogError(SDL_LOG_CATEGORY_APPLICATION, "SDL_Init() failed: %s\n", SDL_GetError());
         return 1;
     }
@@ -71,6 +85,8 @@ int main(int argc, char *argv[])
     report_power();
 
     SDL_Quit();
+    SDLTest_CommonDestroyState(state);
+
     return 0;
 }
 

+ 45 - 17
test/testqsort.c

@@ -10,8 +10,9 @@
   freely.
 */
 
-#include <SDL3/SDL_test.h>
+#include <SDL3/SDL.h>
 #include <SDL3/SDL_main.h>
+#include <SDL3/SDL_test.h>
 
 static int SDLCALL
 num_compare(const void *_a, const void *_b)
@@ -46,34 +47,59 @@ int main(int argc, char *argv[])
 {
     static int nums[1024 * 100];
     static const int itervals[] = { SDL_arraysize(nums), 12 };
+    int i;
     int iteration;
     SDLTest_RandomContext rndctx;
+    SDLTest_CommonState *state;
+    int seed_seen = 0;
 
-    if (argc > 1) {
-        int success;
-        Uint64 seed = 0;
-        if (argv[1][0] == '0' && argv[1][1] == 'x') {
-            success = SDL_sscanf(argv[1] + 2, "%" SDL_PRIx64, &seed);
-        } else {
-            success = SDL_sscanf(argv[1], "%" SDL_PRIu64, &seed);
-        }
-        if (!success) {
-            SDL_LogError(SDL_LOG_CATEGORY_APPLICATION, "Invalid seed. Use a decimal or hexadecimal number.\n");
-            return 1;
+    /* Initialize test framework */
+    state = SDLTest_CommonCreateState(argv, 0);
+    if (state == NULL) {
+        return 1;
+    }
+
+    /* Parse commandline */
+    for (i = 1; i < argc;) {
+        int consumed;
+
+        consumed = SDLTest_CommonArg(state, i);
+        if (!consumed) {
+            if (!seed_seen) {
+                Uint64 seed = 0;
+                char *endptr = NULL;
+
+                seed = SDL_strtoull(argv[i], &endptr, 0);
+                if (endptr != argv[i] && *endptr == '\0') {
+                    seed_seen = 1;
+                    consumed = 1;
+                } else {
+                    SDL_LogError(SDL_LOG_CATEGORY_APPLICATION, "Invalid seed. Use a decimal or hexadecimal number.\n");
+                    return 1;
+                }
+                if (seed <= ((Uint64)0xffffffff)) {
+                    SDL_LogError(SDL_LOG_CATEGORY_APPLICATION, "Seed must be equal or greater than 0x100000000.\n");
+                    return 1;
+                }
+                SDLTest_RandomInit(&rndctx, (unsigned int)(seed >> 32), (unsigned int)(seed & 0xffffffff));
+            }
         }
-        if (seed <= ((Uint64)0xffffffff)) {
-            SDL_LogError(SDL_LOG_CATEGORY_APPLICATION, "Seed must be equal or greater than 0x100000000.\n");
+        if (consumed <= 0) {
+            static const char *options[] = { "[seed]", NULL };
+            SDLTest_CommonLogUsage(state, argv[0], options);
             return 1;
         }
-        SDLTest_RandomInit(&rndctx, (unsigned int)(seed >> 32), (unsigned int)(seed & 0xffffffff));
-    } else {
+
+        i += consumed;
+    }
+
+    if (!seed_seen) {
         SDLTest_RandomInitTime(&rndctx);
     }
     SDL_Log("Using random seed 0x%08x%08x\n", rndctx.x, rndctx.c);
 
     for (iteration = 0; iteration < SDL_arraysize(itervals); iteration++) {
         const int arraylen = itervals[iteration];
-        int i;
 
         for (i = 0; i < arraylen; i++) {
             nums[i] = i;
@@ -97,5 +123,7 @@ int main(int argc, char *argv[])
         test_sort("random sorted", nums, arraylen);
     }
 
+    SDLTest_CommonDestroyState(state);
+
     return 0;
 }

+ 5 - 2
test/testrelative.c

@@ -95,9 +95,12 @@ int main(int argc, char *argv[])
     if (state == NULL) {
         return 1;
     }
-    for (i = 1; i < argc; ++i) {
-        SDLTest_CommonArg(state, i);
+
+    /* Parse commandline */
+    if (!SDLTest_CommonDefaultArgs(state, argc, argv)) {
+        return 1;
     }
+
     if (!SDLTest_CommonInit(state)) {
         return 2;
     }

+ 3 - 3
test/testrendercopyex.c

@@ -115,15 +115,15 @@ int main(int argc, char *argv[])
     int frames;
     Uint64 then, now;
 
-    /* Enable standard application logging */
-    SDL_LogSetPriority(SDL_LOG_CATEGORY_APPLICATION, SDL_LOG_PRIORITY_INFO);
-
     /* Initialize test framework */
     state = SDLTest_CommonCreateState(argv, SDL_INIT_VIDEO);
     if (state == NULL) {
         return 1;
     }
 
+    /* Enable standard application logging */
+    SDL_LogSetPriority(SDL_LOG_CATEGORY_APPLICATION, SDL_LOG_PRIORITY_INFO);
+
     if (!SDLTest_CommonDefaultArgs(state, argc, argv) || !SDLTest_CommonInit(state)) {
         SDLTest_CommonQuit(state);
         return 1;

+ 64 - 10
test/testresample.c

@@ -12,6 +12,12 @@
 
 #include <SDL3/SDL.h>
 #include <SDL3/SDL_main.h>
+#include <SDL3/SDL_test.h>
+
+static void log_usage(char *progname, SDLTest_CommonState *state) {
+    static const char *options[] = { "in.wav", "out.wav", "newfreq", "newchan", NULL };
+    SDLTest_CommonLogUsage(state, progname, options);
+}
 
 int main(int argc, char **argv)
 {
@@ -28,27 +34,74 @@ int main(int argc, char **argv)
     SDL_RWops *io = NULL;
     int dst_len;
     int ret = 0;
+    int argpos = 0;
+    int i;
+    SDLTest_CommonState *state;
+    char *file_in = NULL;
+    char *file_out = NULL;
+
+    /* Initialize test framework */
+    state = SDLTest_CommonCreateState(argv, 0);
+    if (state == NULL) {
+        return 1;
+    }
 
     /* Enable standard application logging */
     SDL_LogSetPriority(SDL_LOG_CATEGORY_APPLICATION, SDL_LOG_PRIORITY_INFO);
 
-    if (argc != 5) {
-        SDL_Log("USAGE: %s in.wav out.wav newfreq newchans\n", argv[0]);
+    /* Parse commandline */
+    for (i = 1; i < argc;) {
+        int consumed;
+
+        consumed = SDLTest_CommonArg(state, i);
+        if (!consumed) {
+            if (argpos == 0) {
+                file_in = argv[i];
+                argpos++;
+                consumed = 1;
+            } else if (argpos == 1) {
+                file_out = argv[i];
+                argpos++;
+                consumed = 1;
+            } else if (argpos == 2) {
+                char *endp;
+                cvtfreq  = (int)SDL_strtoul(argv[i], &endp, 0);
+                if (endp != argv[i] && *endp == '\0') {
+                    argpos++;
+                    consumed = 1;
+                }
+            } else if (argpos == 3) {
+                char *endp;
+                cvtchans = (int)SDL_strtoul(argv[i], &endp, 0);
+                if (endp != argv[i] && *endp == '\0') {
+                    argpos++;
+                    consumed = 1;
+                }
+            }
+        }
+        if (consumed <= 0) {
+            log_usage(argv[0], state);
+            ret = 1;
+            goto end;
+        }
+
+        i += consumed;
+    }
+
+    if (argpos != 4) {
+        log_usage(argv[0], state);
         ret = 1;
         goto end;
     }
 
-    cvtfreq = SDL_atoi(argv[3]);
-    cvtchans = SDL_atoi(argv[4]);
-
     if (SDL_Init(SDL_INIT_AUDIO) == -1) {
         SDL_LogError(SDL_LOG_CATEGORY_APPLICATION, "SDL_Init() failed: %s\n", SDL_GetError());
         ret = 2;
         goto end;
     }
 
-    if (SDL_LoadWAV(argv[1], &spec, &data, &len) == NULL) {
-        SDL_LogError(SDL_LOG_CATEGORY_APPLICATION, "failed to load %s: %s\n", argv[1], SDL_GetError());
+    if (SDL_LoadWAV(file_in, &spec, &data, &len) == NULL) {
+        SDL_LogError(SDL_LOG_CATEGORY_APPLICATION, "failed to load %s: %s\n", file_in, SDL_GetError());
         ret = 3;
         goto end;
     }
@@ -61,9 +114,9 @@ int main(int argc, char **argv)
     }
 
     /* write out a WAV header... */
-    io = SDL_RWFromFile(argv[2], "wb");
+    io = SDL_RWFromFile(file_out, "wb");
     if (io == NULL) {
-        SDL_LogError(SDL_LOG_CATEGORY_APPLICATION, "fopen('%s') failed: %s\n", argv[2], SDL_GetError());
+        SDL_LogError(SDL_LOG_CATEGORY_APPLICATION, "fopen('%s') failed: %s\n", file_out, SDL_GetError());
         ret = 5;
         goto end;
     }
@@ -88,7 +141,7 @@ int main(int argc, char **argv)
     SDL_RWwrite(io, dst_buf, dst_len);
 
     if (SDL_RWclose(io) == -1) {
-        SDL_LogError(SDL_LOG_CATEGORY_APPLICATION, "fclose('%s') failed: %s\n", argv[2], SDL_GetError());
+        SDL_LogError(SDL_LOG_CATEGORY_APPLICATION, "fclose('%s') failed: %s\n", file_out, SDL_GetError());
         ret = 6;
         goto end;
     }
@@ -98,5 +151,6 @@ end:
     SDL_free(data);
     SDL_DestroyAudioStream(stream);
     SDL_Quit();
+    SDLTest_CommonDestroyState(state);
     return ret;
 }

+ 38 - 15
test/testrumble.c

@@ -24,6 +24,7 @@ THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
 
 #include <SDL3/SDL.h>
 #include <SDL3/SDL_main.h>
+#include <SDL3/SDL_test.h>
 
 static SDL_Haptic *haptic;
 
@@ -35,30 +36,50 @@ static SDL_Haptic *haptic;
 int main(int argc, char **argv)
 {
     int i;
-    char *name;
+    char *name = NULL;
     int index;
+    SDLTest_CommonState *state;
+
+    /* Initialize test framework */
+    state = SDLTest_CommonCreateState(argv, 0);
+    if (state == NULL) {
+        return 1;
+    }
 
     /* Enable standard application logging */
     SDL_LogSetPriority(SDL_LOG_CATEGORY_APPLICATION, SDL_LOG_PRIORITY_INFO);
 
     name = NULL;
     index = -1;
-    if (argc > 1) {
-        size_t l;
-        name = argv[1];
-        if ((SDL_strcmp(name, "--help") == 0) || (SDL_strcmp(name, "-h") == 0)) {
-            SDL_Log("USAGE: %s [device]\n"
-                    "If device is a two-digit number it'll use it as an index, otherwise\n"
-                    "it'll use it as if it were part of the device's name.\n",
-                    argv[0]);
-            return 0;
-        }
 
-        l = SDL_strlen(name);
-        if ((l < 3) && SDL_isdigit(name[0]) && ((l == 1) || SDL_isdigit(name[1]))) {
-            index = SDL_atoi(name);
-            name = NULL;
+    /* Parse commandline */
+    for (i = 1; i < argc;) {
+        int consumed;
+
+        consumed = SDLTest_CommonArg(state, i);
+        if (!consumed) {
+            if (!name && index < 0) {
+                size_t l;
+
+                l = SDL_strlen(argv[i]);
+                if ((l < 3) && SDL_isdigit(argv[i][0]) && ((l == 1) || SDL_isdigit(argv[i][1]))) {
+                    index = SDL_atoi(argv[i]);
+                } else {
+                    name = argv[i];
+                }
+                consumed = 1;
+            }
+        }
+        if (consumed <= 0) {
+            static const char *options[] = { "[device]", NULL };
+            SDLTest_CommonLogUsage(state, argv[0], options);
+            SDL_Log("\n");
+            SDL_Log("If device is a two-digit number it'll use it as an index, otherwise\n"
+                    "it'll use it as if it were part of the device's name.\n");
+            return 1;
         }
+
+        i += consumed;
     }
 
     /* Initialize the force feedbackness */
@@ -128,7 +149,9 @@ int main(int argc, char **argv)
     if (haptic != NULL) {
         SDL_HapticClose(haptic);
     }
+
     SDL_Quit();
+    SDLTest_CommonDestroyState(state);
 
     return 0;
 }

+ 9 - 5
test/testscale.c

@@ -102,20 +102,24 @@ int main(int argc, char *argv[])
     int frames;
     Uint64 then, now;
 
-    /* Enable standard application logging */
-    SDL_LogSetPriority(SDL_LOG_CATEGORY_APPLICATION, SDL_LOG_PRIORITY_INFO);
-
     /* Initialize test framework */
     state = SDLTest_CommonCreateState(argv, SDL_INIT_VIDEO);
     if (state == NULL) {
         return 1;
     }
 
-    if (!SDLTest_CommonDefaultArgs(state, argc, argv) || !SDLTest_CommonInit(state)) {
-        SDLTest_CommonQuit(state);
+    /* Enable standard application logging */
+    SDL_LogSetPriority(SDL_LOG_CATEGORY_APPLICATION, SDL_LOG_PRIORITY_INFO);
+
+    /* Parse commandline */
+    if (!SDLTest_CommonDefaultArgs(state, argc, argv)) {
         return 1;
     }
 
+    if (!SDLTest_CommonInit(state)) {
+        quit(1);
+    }
+
     drawstates = SDL_stack_alloc(DrawState, state->num_windows);
     for (i = 0; i < state->num_windows; ++i) {
         DrawState *drawstate = &drawstates[i];

+ 40 - 2
test/testsem.c

@@ -16,6 +16,7 @@
 
 #include <SDL3/SDL.h>
 #include <SDL3/SDL_main.h>
+#include <SDL3/SDL_test.h>
 
 #define NUM_THREADS 10
 /* This value should be smaller than the maximum count of the */
@@ -35,6 +36,11 @@ typedef struct Thread_State
     int content_count;
 } Thread_State;
 
+static void log_usage(char *progname, SDLTest_CommonState *state) {
+    static const char *options[] = { "init_value", NULL };
+    SDLTest_CommonLogUsage(state, progname, options);
+}
+
 static void
 killed(int sig)
 {
@@ -248,13 +254,43 @@ TestOverheadContended(SDL_bool try_wait)
 
 int main(int argc, char **argv)
 {
+    int arg_count = 0;
+    int i;
     int init_sem;
+    SDLTest_CommonState *state;
+
+    /* Initialize test framework */
+    state = SDLTest_CommonCreateState(argv, 0);
+    if (state == NULL) {
+        return 1;
+    }
 
     /* Enable standard application logging */
     SDL_LogSetPriority(SDL_LOG_CATEGORY_APPLICATION, SDL_LOG_PRIORITY_INFO);
 
-    if (argc < 2) {
-        SDL_Log("Usage: %s init_value\n", argv[0]);
+    /* Parse commandline */
+    for (i = 1; i < argc;) {
+        int consumed;
+
+        consumed = SDLTest_CommonArg(state, i);
+        if (arg_count == 0) {
+            char *endptr;
+            init_sem = SDL_strtol(argv[i], &endptr, 0);
+            if (endptr != argv[i] && *endptr == '\0') {
+                arg_count++;
+                consumed = 1;
+            }
+        }
+        if (consumed <= 0) {
+            log_usage(argv[0], state);
+            return 1;
+        }
+
+        i += consumed;
+    }
+
+    if (arg_count != 1) {
+        log_usage(argv[0], state);
         return 1;
     }
 
@@ -280,5 +316,7 @@ int main(int argc, char **argv)
     TestOverheadContended(SDL_TRUE);
 
     SDL_Quit();
+    SDLTest_CommonDestroyState(state);
+
     return 0;
 }

+ 18 - 0
test/testsensor.c

@@ -14,6 +14,7 @@
 
 #include <SDL3/SDL.h>
 #include <SDL3/SDL_main.h>
+#include <SDL3/SDL_test.h>
 
 static const char *GetSensorTypeString(SDL_SensorType type)
 {
@@ -59,10 +60,26 @@ int main(int argc, char **argv)
 {
     SDL_SensorID *sensors;
     int i, num_sensors, num_opened;
+    SDLTest_CommonState *state;
+
+    /* Initialize test framework */
+    state = SDLTest_CommonCreateState(argv, 0);
+    if (state == NULL) {
+        return 1;
+    }
+
+    /* Enable standard application logging */
+    SDL_LogSetPriority(SDL_LOG_CATEGORY_APPLICATION, SDL_LOG_PRIORITY_INFO);
+
+    if (!SDLTest_CommonDefaultArgs(state, argc, argv)) {
+        SDLTest_CommonDestroyState(state);
+        return 1;
+    }
 
     /* Load the SDL library */
     if (SDL_Init(SDL_INIT_SENSOR) < 0) {
         SDL_Log("Couldn't initialize SDL: %s\n", SDL_GetError());
+        SDLTest_CommonDestroyState(state);
         return 1;
     }
 
@@ -119,5 +136,6 @@ int main(int argc, char **argv)
     }
 
     SDL_Quit();
+    SDLTest_CommonDestroyState(state);
     return 0;
 }

+ 37 - 1
test/testshader.c

@@ -13,6 +13,9 @@
 
 #include <SDL3/SDL.h>
 #include <SDL3/SDL_main.h>
+#include <SDL3/SDL_test.h>
+
+#include "testutils.h"
 
 #include <stdlib.h>
 
@@ -440,15 +443,44 @@ static void DrawGLScene(SDL_Window *window, GLuint texture, GLfloat *texcoord)
 
 int main(int argc, char **argv)
 {
+    int i;
     int done;
     SDL_Window *window;
+    char *filename = NULL;
     SDL_Surface *surface;
     GLuint texture;
     GLfloat texcoords[4];
+    SDLTest_CommonState *state;
+
+    /* Initialize test framework */
+    state = SDLTest_CommonCreateState(argv, 0);
+    if (state == NULL) {
+        return 1;
+    }
 
     /* Enable standard application logging */
     SDL_LogSetPriority(SDL_LOG_CATEGORY_APPLICATION, SDL_LOG_PRIORITY_INFO);
 
+    /* Parse commandline */
+    for (i = 1; i < argc;) {
+        int consumed;
+
+        consumed = SDLTest_CommonArg(state, i);
+        if (!consumed) {
+            if (!filename) {
+                filename = argv[i];
+                consumed = 1;
+            }
+        }
+        if (consumed <= 0) {
+            static const char *options[] = { "[icon.bmp]", NULL };
+            SDLTest_CommonLogUsage(state, argv[0], options);
+            exit(1);
+        }
+
+        i += consumed;
+    }
+
     /* Initialize SDL for video output */
     if (SDL_Init(SDL_INIT_VIDEO) < 0) {
         SDL_LogError(SDL_LOG_CATEGORY_APPLICATION, "Unable to initialize SDL: %s\n", SDL_GetError());
@@ -469,7 +501,10 @@ int main(int argc, char **argv)
         exit(2);
     }
 
-    surface = SDL_LoadBMP("icon.bmp");
+    filename = GetResourceFilename(NULL, "icon.bmp");
+    surface = SDL_LoadBMP(filename);
+    SDL_free(filename);
+
     if (surface == NULL) {
         SDL_LogError(SDL_LOG_CATEGORY_APPLICATION, "Unable to load icon.bmp: %s\n", SDL_GetError());
         SDL_Quit();
@@ -509,6 +544,7 @@ int main(int argc, char **argv)
     }
     QuitShaders();
     SDL_Quit();
+    SDLTest_CommonDestroyState(state);
     return 1;
 }
 

+ 101 - 74
test/testshape.c

@@ -13,6 +13,7 @@
 
 #include <SDL3/SDL.h>
 #include <SDL3/SDL_main.h>
+#include <SDL3/SDL_test.h>
 
 #define SHAPED_WINDOW_DIMENSION 640
 
@@ -22,6 +23,7 @@ typedef struct LoadedPicture
     SDL_Texture *texture;
     SDL_WindowShapeMode mode;
     const char *name;
+    struct LoadedPicture *next;
 } LoadedPicture;
 
 static Uint8 *g_bitmap = NULL;
@@ -29,6 +31,11 @@ static int g_bitmap_w = 0, g_bitmap_h = 0;
 static SDL_Surface *g_shape_surface = NULL;
 static SDL_Texture *g_shape_texture = NULL;
 
+static void log_usage(SDLTest_CommonState *state, char *progname) {
+    static const char *options[] = { "sample1.bmp [sample2.bmp [sample3.bmp ...]]", NULL };
+    SDLTest_CommonLogUsage(state, progname, options);
+}
+
 /* REQUIRES that bitmap point to a w-by-h bitmap with ppb pixels-per-byte. */
 static void SDL_CalculateShapeBitmap(SDL_WindowShapeMode mode, SDL_Surface *shape, Uint8 *bitmap, Uint8 ppb)
 {
@@ -198,20 +205,32 @@ static void render(SDL_Renderer *renderer, SDL_Texture *texture)
 
 int main(int argc, char **argv)
 {
-    Uint8 num_pictures;
-    LoadedPicture *pictures;
-    int i, j;
+    int num_pictures = 0;
+    LoadedPicture *pic_i = NULL;
+    LoadedPicture *picture_linked_list = NULL;
+    LoadedPicture **pictures = NULL;
+    int i;
     const SDL_DisplayMode *mode;
     SDL_PixelFormat *format = NULL;
-    SDL_Window *window;
-    SDL_Renderer *renderer;
+    SDL_Window *window = NULL;
+    SDL_Renderer *renderer = NULL;
     SDL_Color black = { 0, 0, 0, 0xff };
     SDL_Event event;
     int should_exit = 0;
-    unsigned int current_picture;
+    int current_picture;
     int button_down;
     Uint32 pixelFormat = 0;
     int w, h, access = 0;
+    SDLTest_CommonState *state;
+    int rc;
+
+    /* Initialize test framework */
+    state = SDLTest_CommonCreateState(argv, 0);
+    if (state == NULL) {
+        return 1;
+    }
+
+    rc = 0;
 
 //    SDL_SetHint(SDL_HINT_RENDER_DRIVER, "software");
 //    SDL_SetHint(SDL_HINT_VIDEO_FORCE_EGL, "0");
@@ -219,8 +238,31 @@ int main(int argc, char **argv)
     /* Enable standard application logging */
     SDL_LogSetPriority(SDL_LOG_CATEGORY_APPLICATION, SDL_LOG_PRIORITY_INFO);
 
-    if (argc < 2) {
+    /* Parse commandline */
+    for (i = 1; i < argc;) {
+        int consumed;
+
+        consumed = SDLTest_CommonArg(state, i);
+        if (!consumed) {
+            LoadedPicture *new_picture;
+
+            new_picture = SDL_malloc(sizeof(LoadedPicture));
+            new_picture->name = argv[i];
+            new_picture->next = picture_linked_list;
+            picture_linked_list = new_picture;
+            num_pictures++;
+            consumed = 1;
+        }
+        if (consumed <= 0) {
+            log_usage(state, argv[0]);
+            exit(-1);
+        }
+
+        i += consumed;
+    }
+    if (!num_pictures) {
         SDL_LogError(SDL_LOG_CATEGORY_APPLICATION, "SDL_Shape requires at least one bitmap file as argument.");
+        log_usage(state, argv[0]);
         exit(-1);
     }
 
@@ -232,94 +274,73 @@ int main(int argc, char **argv)
     mode = SDL_GetDesktopDisplayMode(SDL_GetPrimaryDisplay());
     if (!mode) {
         SDL_LogError(SDL_LOG_CATEGORY_APPLICATION, "Couldn't get desktop display mode: %s", SDL_GetError());
-        exit(-2);
+        rc = -2;
+        goto ret;
     }
 
-    num_pictures = argc - 1;
-    pictures = (LoadedPicture *)SDL_malloc(sizeof(LoadedPicture) * num_pictures);
-    if (pictures == NULL) {
+    /* Allocate an array of LoadedPicture pointers for convenience accesses. */
+    pictures = (LoadedPicture **)SDL_malloc(sizeof(LoadedPicture*) * num_pictures);
+    if (!pictures) {
         SDL_LogError(SDL_LOG_CATEGORY_APPLICATION, "Could not allocate memory.");
-        exit(1);
+        rc = 1;
+        goto ret;
     }
-    for (i = 0; i < num_pictures; i++) {
-        pictures[i].surface = NULL;
+    for (i = 0, pic_i = picture_linked_list; i < num_pictures; i++, pic_i = pic_i->next) {
+        pictures[i] = pic_i;
+        pictures[i]->surface = NULL;
     }
     for (i = 0; i < num_pictures; i++) {
-        pictures[i].surface = SDL_LoadBMP(argv[i + 1]);
-        pictures[i].name = argv[i + 1];
-        if (pictures[i].surface == NULL) {
-            for (j = 0; j < num_pictures; j++) {
-                SDL_DestroySurface(pictures[j].surface);
-            }
-            SDL_free(pictures);
-            SDL_Quit();
-            SDL_LogError(SDL_LOG_CATEGORY_APPLICATION, "Could not load surface from named bitmap file: %s", argv[i + 1]);
-            exit(-3);
+        pictures[i]->surface = SDL_LoadBMP(pictures[i]->name);
+        if (pictures[i]->surface == NULL) {
+            SDL_LogError(SDL_LOG_CATEGORY_APPLICATION, "Could not load surface from named bitmap file: %s", pictures[i]->name);
+            rc = -3;
+            goto ret;
         }
 
-        format = pictures[i].surface->format;
+        format = pictures[i]->surface->format;
         if (SDL_ISPIXELFORMAT_ALPHA(format->format)) {
-            pictures[i].mode.mode = ShapeModeBinarizeAlpha;
-            pictures[i].mode.parameters.binarizationCutoff = 255;
+            pictures[i]->mode.mode = ShapeModeBinarizeAlpha;
+            pictures[i]->mode.parameters.binarizationCutoff = 255;
         } else {
-            pictures[i].mode.mode = ShapeModeColorKey;
-            pictures[i].mode.parameters.colorKey = black;
+            pictures[i]->mode.mode = ShapeModeColorKey;
+            pictures[i]->mode.parameters.colorKey = black;
         }
     }
 
     window = SDL_CreateWindow("SDL_Shape test", SHAPED_WINDOW_DIMENSION, SHAPED_WINDOW_DIMENSION, SDL_WINDOW_TRANSPARENT);
     if (window == NULL) {
-        for (i = 0; i < num_pictures; i++) {
-            SDL_DestroySurface(pictures[i].surface);
-        }
-        SDL_free(pictures);
-        SDL_Quit();
         SDL_LogError(SDL_LOG_CATEGORY_APPLICATION, "Could not create shaped window for SDL_Shape.");
-        exit(-4);
+        rc = -4;
+        goto ret;
     }
     renderer = SDL_CreateRenderer(window, NULL, 0);
     if (renderer == NULL) {
         SDL_DestroyWindow(window);
-        for (i = 0; i < num_pictures; i++) {
-            SDL_DestroySurface(pictures[i].surface);
-        }
-        SDL_free(pictures);
-        SDL_Quit();
         SDL_LogError(SDL_LOG_CATEGORY_APPLICATION, "Could not create rendering context for SDL_Shape window.");
-        exit(-5);
+        rc = -4;
+        goto ret;
     }
 
     for (i = 0; i < num_pictures; i++) {
-        pictures[i].texture = NULL;
+        pictures[i]->texture = NULL;
     }
     for (i = 0; i < num_pictures; i++) {
-        pictures[i].texture = SDL_CreateTextureFromSurface(renderer, pictures[i].surface);
-        if (pictures[i].texture == NULL) {
-            for (i = 0; i < num_pictures; i++) {
-                if (pictures[i].texture != NULL) {
-                    SDL_DestroyTexture(pictures[i].texture);
-                }
-            }
-            for (i = 0; i < num_pictures; i++) {
-                SDL_DestroySurface(pictures[i].surface);
-            }
-            SDL_free(pictures);
-            SDL_DestroyRenderer(renderer);
-            SDL_DestroyWindow(window);
-            SDL_Quit();
+        pictures[i]->texture = SDL_CreateTextureFromSurface(renderer, pictures[i]->surface);
+        if (pictures[i]->texture == NULL) {
             SDL_LogError(SDL_LOG_CATEGORY_APPLICATION, "Could not create texture for SDL_shape.");
-            exit(-6);
+            rc = -6;
+            goto ret;
         }
     }
 
     should_exit = 0;
     current_picture = 0;
     button_down = 0;
-    SDL_LogInfo(SDL_LOG_CATEGORY_APPLICATION, "Changing to shaped bmp: %s", pictures[current_picture].name);
-    SDL_QueryTexture(pictures[current_picture].texture, &pixelFormat, &access, &w, &h);
+    SDL_LogInfo(SDL_LOG_CATEGORY_APPLICATION, "Changing to shaped bmp: %s", pictures[current_picture]->name);
+    SDL_QueryTexture(pictures[current_picture]->texture, &pixelFormat, &access, &w, &h);
     /* We want to set the window size in pixels */
     SDL_SetWindowSize(window, (int)SDL_ceilf(w / mode->display_scale), (int)SDL_ceilf(h / mode->display_scale));
-    SDL3_SetWindowShape(window, pictures[current_picture].surface, &pictures[current_picture].mode);
+    SDL3_SetWindowShape(window, pictures[current_picture]->surface, &pictures[current_picture]->mode);
     while (should_exit == 0) {
         while (SDL_PollEvent(&event)) {
             if (event.type == SDL_EVENT_KEY_DOWN) {
@@ -335,34 +356,40 @@ int main(int argc, char **argv)
                 if (current_picture >= num_pictures) {
                     current_picture = 0;
                 }
-                SDL_LogInfo(SDL_LOG_CATEGORY_APPLICATION, "Changing to shaped bmp: %s", pictures[current_picture].name);
-                SDL_QueryTexture(pictures[current_picture].texture, &pixelFormat, &access, &w, &h);
+                SDL_LogInfo(SDL_LOG_CATEGORY_APPLICATION, "Changing to shaped bmp: %s", pictures[current_picture]->name);
+                SDL_QueryTexture(pictures[current_picture]->texture, &pixelFormat, &access, &w, &h);
                 SDL_SetWindowSize(window, (int)SDL_ceilf(w / mode->display_scale), (int)SDL_ceilf(h / mode->display_scale));
-                SDL3_SetWindowShape(window, pictures[current_picture].surface, &pictures[current_picture].mode);
+                SDL3_SetWindowShape(window, pictures[current_picture]->surface, &pictures[current_picture]->mode);
             }
             if (event.type == SDL_EVENT_QUIT) {
                 should_exit = 1;
                 break;
             }
         }
-        render(renderer, pictures[current_picture].texture);
+        render(renderer, pictures[current_picture]->texture);
         SDL_Delay(10);
     }
 
-    /* Free the textures. */
-    for (i = 0; i < num_pictures; i++) {
-        SDL_DestroyTexture(pictures[i].texture);
+ret:
+    /* Free the textures + original surfaces backing the textures. */
+    for (pic_i = picture_linked_list; pic_i; ) {
+        LoadedPicture *next = pic_i->next;
+        if (pic_i->texture) {
+            SDL_DestroyTexture(pic_i->texture);
+        }
+        SDL_DestroySurface(pic_i->surface);
+        SDL_free(pic_i);
+        pic_i = next;
     }
+    SDL_free(pictures);
+
+    /* Destroy the renderer. */
     SDL_DestroyRenderer(renderer);
     /* Destroy the window. */
     SDL_DestroyWindow(window);
-    /* Free the original surfaces backing the textures. */
-    for (i = 0; i < num_pictures; i++) {
-        SDL_DestroySurface(pictures[i].surface);
-    }
-    SDL_free(pictures);
-    /* Call SDL_Quit() before quitting. */
+
     SDL_Quit();
+    SDLTest_CommonDestroyState(state);
 
-    return 0;
+    return rc;
 }

+ 14 - 0
test/teststreaming.c

@@ -23,6 +23,7 @@
 
 #include <SDL3/SDL.h>
 #include <SDL3/SDL_main.h>
+#include <SDL3/SDL_test.h>
 #include "testutils.h"
 
 #define MOOSEPIC_W 64
@@ -63,10 +64,12 @@ static SDL_Renderer *renderer;
 static int frame;
 static SDL_Texture *MooseTexture;
 static SDL_bool done = SDL_FALSE;
+SDLTest_CommonState *state;
 
 static void quit(int rc)
 {
     SDL_Quit();
+    SDLTest_CommonDestroyState(state);
     exit(rc);
 }
 
@@ -131,9 +134,20 @@ int main(int argc, char **argv)
     SDL_RWops *handle;
     char *filename = NULL;
 
+    /* Initialize test framework */
+    state = SDLTest_CommonCreateState(argv, 0);
+    if (state == NULL) {
+        return 1;
+    }
+
     /* Enable standard application logging */
     SDL_LogSetPriority(SDL_LOG_CATEGORY_APPLICATION, SDL_LOG_PRIORITY_INFO);
 
+    if (!SDLTest_CommonDefaultArgs(state, argc, argv)) {
+        SDLTest_CommonDestroyState(state);
+        return 1;
+    }
+
     if (SDL_Init(SDL_INIT_VIDEO) < 0) {
         SDL_LogError(SDL_LOG_CATEGORY_APPLICATION, "Couldn't initialize SDL: %s\n", SDL_GetError());
         return 1;

+ 13 - 0
test/testsurround.c

@@ -13,6 +13,7 @@
 /* Program to test surround sound audio channels */
 #include <SDL3/SDL.h>
 #include <SDL3/SDL_main.h>
+#include <SDL3/SDL_test.h>
 
 static int total_channels;
 static int active_channel;
@@ -132,10 +133,22 @@ static void SDLCALL fill_buffer(void *unused, Uint8 *stream, int len)
 int main(int argc, char *argv[])
 {
     int i;
+    SDLTest_CommonState *state;
+
+    /* Initialize test framework */
+    state = SDLTest_CommonCreateState(argv, 0);
+    if (state == NULL) {
+        return 1;
+    }
 
     /* Enable standard application logging */
     SDL_LogSetPriority(SDL_LOG_CATEGORY_APPLICATION, SDL_LOG_PRIORITY_INFO);
 
+    if (!SDLTest_CommonDefaultArgs(state, argc, argv)) {
+        SDLTest_CommonQuit(state);
+        return 1;
+    }
+
     if (SDL_Init(SDL_INIT_AUDIO) < 0) {
         SDL_LogError(SDL_LOG_CATEGORY_APPLICATION, "Couldn't initialize SDL: %s\n", SDL_GetError());
         return 1;

+ 36 - 6
test/testtimer.c

@@ -15,6 +15,7 @@
 */
 #include <SDL3/SDL.h>
 #include <SDL3/SDL_main.h>
+#include <SDL3/SDL_test.h>
 
 #define DEFAULT_RESOLUTION 1
 
@@ -36,14 +37,46 @@ callback(Uint32 interval, void *param)
 
 int main(int argc, char *argv[])
 {
-    int i, desired;
+    int i;
+    int desired = -1;
     SDL_TimerID t1, t2, t3;
     Uint64 start, now;
     Uint64 start_perf, now_perf;
+    SDLTest_CommonState  *state;
+
+    /* Initialize test framework */
+    state = SDLTest_CommonCreateState(argv, 0);
+    if (state == NULL) {
+        return 1;
+    }
 
     /* Enable standard application logging */
     SDL_LogSetPriority(SDL_LOG_CATEGORY_APPLICATION, SDL_LOG_PRIORITY_INFO);
 
+    /* Parse commandline */
+    for (i = 1; i < argc;) {
+        int consumed;
+
+        consumed = SDLTest_CommonArg(state, i);
+        if (!consumed) {
+            if (desired < 0) {
+                char *endptr;
+
+                desired = SDL_strtoul(argv[i], &endptr, 0);
+                if (desired != 0 && endptr != argv[i] && *endptr == '\0') {
+                    consumed = 1;
+                }
+            }
+        }
+        if (consumed <= 0) {
+            static const char *options[] = { "[interval]", NULL };
+            SDLTest_CommonLogUsage(state, argv[0], options);
+            return 1;
+        }
+
+        i += consumed;
+    }
+
     if (SDL_Init(SDL_INIT_TIMER) < 0) {
         SDL_LogError(SDL_LOG_CATEGORY_APPLICATION, "Couldn't initialize SDL: %s\n", SDL_GetError());
         return 1;
@@ -69,11 +102,7 @@ int main(int argc, char *argv[])
     }
 
     /* Start the timer */
-    desired = 0;
-    if (argv[1]) {
-        desired = SDL_atoi(argv[1]);
-    }
-    if (desired == 0) {
+    if (desired < 0) {
         desired = DEFAULT_RESOLUTION;
     }
     t1 = SDL_AddTimer(desired, ticktock, NULL);
@@ -133,6 +162,7 @@ int main(int argc, char *argv[])
     now = SDL_GetTicks();
     SDL_Log("Delay 1 second = %d ms in ticks, %f ms according to performance counter\n", (int)(now - start), (double)((now_perf - start_perf) * 1000) / SDL_GetPerformanceFrequency());
 
+    SDLTest_CommonDestroyState(state);
     SDL_Quit();
     return 0;
 }

+ 3 - 3
test/testvulkan.c

@@ -1094,15 +1094,15 @@ int main(int argc, char **argv)
     Uint32 frames;
     int dw, dh;
 
-    /* Enable standard application logging */
-    SDL_LogSetPriority(SDL_LOG_CATEGORY_APPLICATION, SDL_LOG_PRIORITY_INFO);
-
     /* Initialize test framework */
     state = SDLTest_CommonCreateState(argv, SDL_INIT_VIDEO);
     if (state == NULL) {
         return 1;
     }
 
+    /* Enable standard application logging */
+    SDL_LogSetPriority(SDL_LOG_CATEGORY_APPLICATION, SDL_LOG_PRIORITY_INFO);
+
     /* Set Vulkan parameters */
     state->window_flags |= SDL_WINDOW_VULKAN;
     state->skip_renderer = 1;

+ 5 - 5
test/testwm.c

@@ -259,17 +259,17 @@ int main(int argc, char *argv[])
 {
     int i;
 
-    /* Enable standard application logging */
-    SDL_LogSetPriority(SDL_LOG_CATEGORY_APPLICATION, SDL_LOG_PRIORITY_INFO);
-
-    SDL_assert(SDL_arraysize(cursorNames) == SDL_NUM_SYSTEM_CURSORS);
-
     /* Initialize test framework */
     state = SDLTest_CommonCreateState(argv, SDL_INIT_VIDEO);
     if (state == NULL) {
         return 1;
     }
 
+    /* Enable standard application logging */
+    SDL_LogSetPriority(SDL_LOG_CATEGORY_APPLICATION, SDL_LOG_PRIORITY_INFO);
+
+    SDL_assert(SDL_arraysize(cursorNames) == SDL_NUM_SYSTEM_CURSORS);
+
     if (!SDLTest_CommonDefaultArgs(state, argc, argv) || !SDLTest_CommonInit(state)) {
         SDLTest_CommonQuit(state);
         return 1;

+ 99 - 53
test/testyuv.c

@@ -11,8 +11,9 @@
 */
 #include <SDL3/SDL.h>
 #include <SDL3/SDL_main.h>
-#include <SDL3/SDL_test_font.h>
+#include <SDL3/SDL_test.h>
 #include "testyuv_cvt.h"
+#include "testutils.h"
 
 /* 422 (YUY2, etc) formats are the largest */
 #define MAX_YUV_SURFACE_SIZE(W, H, P) (H * 4 * (W + P + 1) / 2)
@@ -239,8 +240,7 @@ int main(int argc, char **argv)
         { SDL_TRUE, 33, 3 },
         { SDL_TRUE, 37, 3 },
     };
-    int arg = 1;
-    const char *filename;
+    char *filename = NULL;
     SDL_Surface *original;
     SDL_Surface *converted;
     SDL_Window *window;
@@ -256,58 +256,106 @@ int main(int argc, char **argv)
     int pitch;
     Uint8 *raw_yuv;
     Uint64 then, now;
-    Uint32 i, iterations = 100;
+    int i, iterations = 100;
     SDL_bool should_run_automated_tests = SDL_FALSE;
+    SDLTest_CommonState *state;
 
-    while (argv[arg] && *argv[arg] == '-') {
-        if (SDL_strcmp(argv[arg], "--jpeg") == 0) {
-            SDL_SetYUVConversionMode(SDL_YUV_CONVERSION_JPEG);
-        } else if (SDL_strcmp(argv[arg], "--bt601") == 0) {
-            SDL_SetYUVConversionMode(SDL_YUV_CONVERSION_BT601);
-        } else if (SDL_strcmp(argv[arg], "--bt709") == 0) {
-            SDL_SetYUVConversionMode(SDL_YUV_CONVERSION_BT709);
-        } else if (SDL_strcmp(argv[arg], "--auto") == 0) {
-            SDL_SetYUVConversionMode(SDL_YUV_CONVERSION_AUTOMATIC);
-        } else if (SDL_strcmp(argv[arg], "--yv12") == 0) {
-            yuv_format = SDL_PIXELFORMAT_YV12;
-        } else if (SDL_strcmp(argv[arg], "--iyuv") == 0) {
-            yuv_format = SDL_PIXELFORMAT_IYUV;
-        } else if (SDL_strcmp(argv[arg], "--yuy2") == 0) {
-            yuv_format = SDL_PIXELFORMAT_YUY2;
-        } else if (SDL_strcmp(argv[arg], "--uyvy") == 0) {
-            yuv_format = SDL_PIXELFORMAT_UYVY;
-        } else if (SDL_strcmp(argv[arg], "--yvyu") == 0) {
-            yuv_format = SDL_PIXELFORMAT_YVYU;
-        } else if (SDL_strcmp(argv[arg], "--nv12") == 0) {
-            yuv_format = SDL_PIXELFORMAT_NV12;
-        } else if (SDL_strcmp(argv[arg], "--nv21") == 0) {
-            yuv_format = SDL_PIXELFORMAT_NV21;
-        } else if (SDL_strcmp(argv[arg], "--rgb555") == 0) {
-            rgb_format = SDL_PIXELFORMAT_RGB555;
-        } else if (SDL_strcmp(argv[arg], "--rgb565") == 0) {
-            rgb_format = SDL_PIXELFORMAT_RGB565;
-        } else if (SDL_strcmp(argv[arg], "--rgb24") == 0) {
-            rgb_format = SDL_PIXELFORMAT_RGB24;
-        } else if (SDL_strcmp(argv[arg], "--argb") == 0) {
-            rgb_format = SDL_PIXELFORMAT_ARGB8888;
-        } else if (SDL_strcmp(argv[arg], "--abgr") == 0) {
-            rgb_format = SDL_PIXELFORMAT_ABGR8888;
-        } else if (SDL_strcmp(argv[arg], "--rgba") == 0) {
-            rgb_format = SDL_PIXELFORMAT_RGBA8888;
-        } else if (SDL_strcmp(argv[arg], "--bgra") == 0) {
-            rgb_format = SDL_PIXELFORMAT_BGRA8888;
-        } else if (SDL_strcmp(argv[arg], "--automated") == 0) {
-            should_run_automated_tests = SDL_TRUE;
-        } else {
-            SDL_LogError(SDL_LOG_CATEGORY_APPLICATION, "Usage: %s [--jpeg|--bt601|-bt709|--auto] [--yv12|--iyuv|--yuy2|--uyvy|--yvyu|--nv12|--nv21] [--rgb555|--rgb565|--rgb24|--argb|--abgr|--rgba|--bgra] [image_filename]\n", argv[0]);
+    /* Initialize test framework */
+    state = SDLTest_CommonCreateState(argv, 0);
+    if (state == NULL) {
+        return 1;
+    }
+
+    /* Enable standard application logging */
+    SDL_LogSetPriority(SDL_LOG_CATEGORY_APPLICATION, SDL_LOG_PRIORITY_INFO);
+
+    /* Parse commandline */
+    for (i = 1; i < argc;) {
+        int consumed;
+
+        consumed = SDLTest_CommonArg(state, i);
+        if (!consumed) {
+            if (SDL_strcmp(argv[i], "--jpeg") == 0) {
+                SDL_SetYUVConversionMode(SDL_YUV_CONVERSION_JPEG);
+                consumed = 1;
+            } else if (SDL_strcmp(argv[i], "--bt601") == 0) {
+                SDL_SetYUVConversionMode(SDL_YUV_CONVERSION_BT601);
+                consumed = 1;
+            } else if (SDL_strcmp(argv[i], "--bt709") == 0) {
+                SDL_SetYUVConversionMode(SDL_YUV_CONVERSION_BT709);
+                consumed = 1;
+            } else if (SDL_strcmp(argv[i], "--auto") == 0) {
+                SDL_SetYUVConversionMode(SDL_YUV_CONVERSION_AUTOMATIC);
+                consumed = 1;
+            } else if (SDL_strcmp(argv[i], "--yv12") == 0) {
+                yuv_format = SDL_PIXELFORMAT_YV12;
+                consumed = 1;
+            } else if (SDL_strcmp(argv[i], "--iyuv") == 0) {
+                yuv_format = SDL_PIXELFORMAT_IYUV;
+                consumed = 1;
+            } else if (SDL_strcmp(argv[i], "--yuy2") == 0) {
+                yuv_format = SDL_PIXELFORMAT_YUY2;
+                consumed = 1;
+            } else if (SDL_strcmp(argv[i], "--uyvy") == 0) {
+                yuv_format = SDL_PIXELFORMAT_UYVY;
+                consumed = 1;
+            } else if (SDL_strcmp(argv[i], "--yvyu") == 0) {
+                yuv_format = SDL_PIXELFORMAT_YVYU;
+                consumed = 1;
+            } else if (SDL_strcmp(argv[i], "--nv12") == 0) {
+                yuv_format = SDL_PIXELFORMAT_NV12;
+                consumed = 1;
+            } else if (SDL_strcmp(argv[i], "--nv21") == 0) {
+                yuv_format = SDL_PIXELFORMAT_NV21;
+                consumed = 1;
+            } else if (SDL_strcmp(argv[i], "--rgb555") == 0) {
+                rgb_format = SDL_PIXELFORMAT_RGB555;
+                consumed = 1;
+            } else if (SDL_strcmp(argv[i], "--rgb565") == 0) {
+                rgb_format = SDL_PIXELFORMAT_RGB565;
+                consumed = 1;
+            } else if (SDL_strcmp(argv[i], "--rgb24") == 0) {
+                rgb_format = SDL_PIXELFORMAT_RGB24;
+                consumed = 1;
+            } else if (SDL_strcmp(argv[i], "--argb") == 0) {
+                rgb_format = SDL_PIXELFORMAT_ARGB8888;
+                consumed = 1;
+            } else if (SDL_strcmp(argv[i], "--abgr") == 0) {
+                rgb_format = SDL_PIXELFORMAT_ABGR8888;
+                consumed = 1;
+            } else if (SDL_strcmp(argv[i], "--rgba") == 0) {
+                rgb_format = SDL_PIXELFORMAT_RGBA8888;
+                consumed = 1;
+            } else if (SDL_strcmp(argv[i], "--bgra") == 0) {
+                rgb_format = SDL_PIXELFORMAT_BGRA8888;
+                consumed = 1;
+            } else if (SDL_strcmp(argv[i], "--automated") == 0) {
+                should_run_automated_tests = SDL_TRUE;
+                consumed = 1;
+            } else if (!filename) {
+                filename = argv[i];
+                consumed = 1;
+            }
+        }
+        if (consumed <= 0) {
+            static const char *options[] = {
+                "[--jpeg|--bt601|-bt709|--auto]",
+                "[--yv12|--iyuv|--yuy2|--uyvy|--yvyu|--nv12|--nv21]",
+                "[--rgb555|--rgb565|--rgb24|--argb|--abgr|--rgba|--bgra]",
+                "[--automated]",
+                "[sample.bmp]",
+                NULL,
+            };
+            SDLTest_CommonLogUsage(state, argv[0], options);
+            SDLTest_CommonDestroyState(state);
             return 1;
         }
-        ++arg;
+        i += consumed;
     }
 
     /* Run automated tests */
     if (should_run_automated_tests) {
-        for (i = 0; i < SDL_arraysize(automated_test_params); ++i) {
+        for (i = 0; i < (int)SDL_arraysize(automated_test_params); ++i) {
             SDL_LogInfo(SDL_LOG_CATEGORY_APPLICATION, "Running automated test, pattern size %d, extra pitch %d, intrinsics %s\n",
                         automated_test_params[i].pattern_size,
                         automated_test_params[i].extra_pitch,
@@ -319,11 +367,7 @@ int main(int argc, char **argv)
         return 0;
     }
 
-    if (argv[arg]) {
-        filename = argv[arg];
-    } else {
-        filename = "testyuv.bmp";
-    }
+    filename = GetResourceFilename(filename, "testyuv.bmp");
     original = SDL_ConvertSurfaceFormat(SDL_LoadBMP(filename), SDL_PIXELFORMAT_RGB24);
     if (original == NULL) {
         SDL_LogError(SDL_LOG_CATEGORY_APPLICATION, "Couldn't load %s: %s\n", filename, SDL_GetError());
@@ -347,7 +391,7 @@ int main(int argc, char **argv)
         SDL_ConvertPixels(original->w, original->h, yuv_format, raw_yuv, pitch, rgb_format, converted->pixels, converted->pitch);
     }
     now = SDL_GetTicks();
-    SDL_LogInfo(SDL_LOG_CATEGORY_APPLICATION, "%" SDL_PRIu32 " iterations in %" SDL_PRIu64 " ms, %.2fms each\n", iterations, (now - then), (float)(now - then) / iterations);
+    SDL_LogInfo(SDL_LOG_CATEGORY_APPLICATION, "%d iterations in %" SDL_PRIu64 " ms, %.2fms each\n", iterations, (now - then), (float)(now - then) / iterations);
 
     window = SDL_CreateWindow("YUV test", original->w, original->h, 0);
     if (window == NULL) {
@@ -437,6 +481,8 @@ int main(int argc, char **argv)
             SDL_Delay(10);
         }
     }
+    SDL_free(filename);
     SDL_Quit();
+    SDLTest_CommonDestroyState(state);
     return 0;
 }

+ 14 - 0
test/torturethread.c

@@ -17,6 +17,7 @@
 
 #include <SDL3/SDL.h>
 #include <SDL3/SDL_main.h>
+#include <SDL3/SDL_test.h>
 
 #define NUMTHREADS 10
 
@@ -76,6 +77,13 @@ int main(int argc, char *argv[])
 {
     SDL_Thread *threads[NUMTHREADS];
     int i;
+    SDLTest_CommonState *state;
+
+    /* Initialize test framework */
+    state = SDLTest_CommonCreateState(argv, 0);
+    if (state == NULL) {
+        return 1;
+    }
 
     /* Enable standard application logging */
     SDL_LogSetPriority(SDL_LOG_CATEGORY_APPLICATION, SDL_LOG_PRIORITY_INFO);
@@ -86,6 +94,11 @@ int main(int argc, char *argv[])
         return 1;
     }
 
+    if (!SDLTest_CommonDefaultArgs(state, argc, argv)) {
+        SDLTest_CommonDestroyState(state);
+        return 1;
+    }
+
     (void)signal(SIGSEGV, SIG_DFL);
     for (i = 0; i < NUMTHREADS; i++) {
         char name[64];
@@ -107,5 +120,6 @@ int main(int argc, char *argv[])
         SDL_WaitThread(threads[i], NULL);
     }
     SDL_Quit();
+    SDLTest_CommonDestroyState(state);
     return 0;
 }