SDL: testlock: parse arguments using SDLTest_CommonState + extra arguments

From 64b739bc1e8ee19cc65a7e5105e15331a300054a Mon Sep 17 00:00:00 2001
From: Anonymous Maarten <[EMAIL REDACTED]>
Date: Thu, 16 Mar 2023 16:56:16 +0100
Subject: [PATCH] testlock: parse arguments using SDLTest_CommonState + extra
 arguments

---
 test/testlock.c | 115 +++++++++++++++++++++++++++++++++++++++++-------
 1 file changed, 100 insertions(+), 15 deletions(-)

diff --git a/test/testlock.c b/test/testlock.c
index a4abc0bd3393..a0189e4b25e4 100644
--- a/test/testlock.c
+++ b/test/testlock.c
@@ -19,11 +19,15 @@
 
 #include <SDL3/SDL.h>
 #include <SDL3/SDL_main.h>
+#include <SDL3/SDL_test.h>
 
 static SDL_mutex *mutex = NULL;
 static SDL_threadID mainthread;
-static SDL_Thread *threads[6];
 static SDL_AtomicInt doterminate;
+static int nb_threads = 6;
+static SDL_Thread **threads;
+static int worktime = 1000;
+static SDLTest_CommonState *state;
 
 /**
  * SDL_Quit() shouldn't be used with atexit() directly because
@@ -33,11 +37,12 @@ static void
 SDL_Quit_Wrapper(void)
 {
     SDL_Quit();
+    SDLTest_CommonDestroyState(state);
 }
 
 static void printid(void)
 {
-    SDL_Log("Process %lu:  exiting\n", SDL_ThreadID());
+    SDL_Log("Thread %lu:  exiting\n", SDL_ThreadID());
 }
 
 static void terminate(int sig)
@@ -50,30 +55,35 @@ static void closemutex(int sig)
 {
     SDL_threadID id = SDL_ThreadID();
     int i;
-    SDL_Log("Process %lu:  Cleaning up...\n", id == mainthread ? 0 : id);
+    SDL_Log("Thread %lu:  Cleaning up...\n", id == mainthread ? 0 : id);
     SDL_AtomicSet(&doterminate, 1);
-    for (i = 0; i < 6; ++i) {
-        SDL_WaitThread(threads[i], NULL);
+    if (threads) {
+        for (i = 0; i < nb_threads; ++i) {
+            SDL_WaitThread(threads[i], NULL);
+        }
+        SDL_free(threads);
+        threads = NULL;
     }
     SDL_DestroyMutex(mutex);
     exit(sig);
 }
 
 static int SDLCALL
-Run(void *data)
+DoWork(void *data)
 {
     if (SDL_ThreadID() == mainthread) {
         (void)signal(SIGTERM, closemutex);
     }
+    SDL_Log("Thread %lu: starting up", SDL_ThreadID());
     while (!SDL_AtomicGet(&doterminate)) {
-        SDL_Log("Process %lu ready to work\n", SDL_ThreadID());
+        SDL_Log("Thread %lu: ready to work\n", SDL_ThreadID());
         if (SDL_LockMutex(mutex) < 0) {
             SDL_LogError(SDL_LOG_CATEGORY_APPLICATION, "Couldn't lock mutex: %s", SDL_GetError());
             exit(1);
         }
-        SDL_Log("Process %lu, working!\n", SDL_ThreadID());
-        SDL_Delay(1 * 1000);
-        SDL_Log("Process %lu, done!\n", SDL_ThreadID());
+        SDL_Log("Thread %lu: start work!\n", SDL_ThreadID());
+        SDL_Delay(1 * worktime);
+        SDL_Log("Thread %lu: work done!\n", SDL_ThreadID());
         if (SDL_UnlockMutex(mutex) < 0) {
             SDL_LogError(SDL_LOG_CATEGORY_APPLICATION, "Couldn't unlock mutex: %s", SDL_GetError());
             exit(1);
@@ -82,19 +92,87 @@ Run(void *data)
         SDL_Delay(10);
     }
     if (SDL_ThreadID() == mainthread && SDL_AtomicGet(&doterminate)) {
-        SDL_Log("Process %lu:  raising SIGTERM\n", SDL_ThreadID());
+        SDL_Log("Thread %lu: raising SIGTERM\n", SDL_ThreadID());
         (void)raise(SIGTERM);
     }
+    SDL_Log("Thread %lu: exiting!\n", SDL_ThreadID());
+    return 0;
+}
+
+#if !defined(_WIN32)
+Uint32 hit_timeout(Uint32 interval, void *param) {
+    SDL_Log("Hit timeout! Sending SIGINT!");
+    kill(0, SIGINT);
     return 0;
 }
+#endif
 
 int main(int argc, char *argv[])
 {
     int i;
-    int maxproc = 6;
+#if !defined(_WIN32)
+    int timeout = 0;
+#endif
+
+    /* 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], "--nbthreads") == 0) {
+                if (argv[i + 1]) {
+                    char *endptr;
+                    nb_threads = SDL_strtol(argv[i + 1], &endptr, 0);
+                    if (endptr != argv[i + 1] && *endptr == '\0' && nb_threads > 0) {
+                        consumed = 2;
+                    }
+                }
+            } else if (SDL_strcmp(argv[i], "--worktime") == 0) {
+                if (argv[i + 1]) {
+                    char *endptr;
+                    nb_threads = SDL_strtol(argv[i + 1], &endptr, 0);
+                    if (endptr != argv[i + 1] && *endptr == '\0' && nb_threads > 0) {
+                        consumed = 2;
+                    }
+                }
+#if !defined(_WIN32)
+            } else if (SDL_strcmp(argv[i], "--timeout") == 0) {
+                if (argv[i + 1]) {
+                    char *endptr;
+                    timeout = SDL_strtol(argv[i + 1], &endptr, 0);
+                    if (endptr != argv[i + 1] && *endptr == '\0' && timeout > 0) {
+                        consumed = 2;
+                    }
+                }
+#endif
+            }
+        }
+        if (consumed <= 0) {
+            static const char *options[] = {
+                "[--nbthreads NB]",
+                "[--worktime ms]",
+#if !defined(_WIN32)
+                "[--timeout ms]",
+#endif
+                NULL,
+            };
+            SDLTest_CommonLogUsage(state, argv[0], options);
+            exit(1);
+        }
+
+        i += consumed;
+    }
+
+    threads = SDL_malloc(nb_threads * sizeof(SDL_Thread*));
 
     /* Load the SDL library */
     if (SDL_Init(0) < 0) {
@@ -114,16 +192,23 @@ int main(int argc, char *argv[])
     mainthread = SDL_ThreadID();
     SDL_Log("Main thread: %lu\n", mainthread);
     (void)atexit(printid);
-    for (i = 0; i < maxproc; ++i) {
+    for (i = 0; i < nb_threads; ++i) {
         char name[64];
         (void)SDL_snprintf(name, sizeof(name), "Worker%d", i);
-        threads[i] = SDL_CreateThread(Run, name, NULL);
+        threads[i] = SDL_CreateThread(DoWork, name, &threads[i]);
         if (threads[i] == NULL) {
             SDL_LogError(SDL_LOG_CATEGORY_APPLICATION, "Couldn't create thread!\n");
         }
     }
+
+#if !defined(_WIN32)
+    if (timeout) {
+        SDL_AddTimer(timeout, hit_timeout, NULL);
+    }
+#endif
+
     (void)signal(SIGINT, terminate);
-    Run(NULL);
+    DoWork(NULL);
 
     return 0; /* Never reached */
 }