SDL: Expanded automated clipboard tests

From c1b11ad54e06de29ab25d324fccb24ef3b0e7a9d Mon Sep 17 00:00:00 2001
From: Sam Lantinga <[EMAIL REDACTED]>
Date: Wed, 5 Jul 2023 13:35:26 -0700
Subject: [PATCH] Expanded automated clipboard tests

---
 test/testautomation_clipboard.c | 633 ++++++++++++++++++++------------
 1 file changed, 407 insertions(+), 226 deletions(-)

diff --git a/test/testautomation_clipboard.c b/test/testautomation_clipboard.c
index 2c31664e3a89..c0be19684471 100644
--- a/test/testautomation_clipboard.c
+++ b/test/testautomation_clipboard.c
@@ -7,166 +7,367 @@
 
 /* ================= Test Case Implementation ================== */
 
-/* Test case functions */
+static int clipboard_update_count;
 
-/**
- * \brief Check call to SDL_HasClipboardText
- *
- * \sa SDL_HasClipboardText
- */
-static int clipboard_testHasClipboardText(void *arg)
+static int ClipboardEventWatch(void *userdata, SDL_Event *event)
 {
-    SDL_HasClipboardText();
-    SDLTest_AssertPass("Call to SDL_HasClipboardText succeeded");
-
-    return TEST_COMPLETED;
+    if (event->type == SDL_EVENT_CLIPBOARD_UPDATE) {
+        ++clipboard_update_count;
+    }
+    return 0;
 }
 
-/**
- * \brief Check call to SDL_HasClipboardData
- *
- * \sa SDL_HasClipboardData
- */
-static int clipboard_testHasClipboardData(void *arg)
+enum
 {
-    SDL_HasClipboardData("image/png");
-    SDLTest_AssertPass("Call to SDL_HasClipboardData succeeded");
-
-    return TEST_COMPLETED;
-}
+    TEST_MIME_TYPE_TEXT,
+    TEST_MIME_TYPE_CUSTOM_TEXT,
+    TEST_MIME_TYPE_DATA,
+    NUM_TEST_MIME_TYPES
+};
+static const char *test_mime_types[] = {
+    "text/plain;charset=utf-8",
+    "test/text",
+    "test/data"
+};
+SDL_COMPILE_TIME_ASSERT(test_mime_types, SDL_arraysize(test_mime_types) == NUM_TEST_MIME_TYPES);
 
-/**
- * \brief Check call to SDL_HasPrimarySelectionText
- *
- * \sa SDL_HasPrimarySelectionText
- */
-static int clipboard_testHasPrimarySelectionText(void *arg)
+typedef struct
 {
-    SDL_HasPrimarySelectionText();
-    SDLTest_AssertPass("Call to SDL_HasPrimarySelectionText succeeded");
+    const void *data;
+    size_t data_size;
+} TestClipboardData;
 
-    return TEST_COMPLETED;
-}
+static int clipboard_callback_count;
 
-/**
- * \brief Check call to SDL_GetClipboardText
- *
- * \sa SDL_GetClipboardText
- */
-static int clipboard_testGetClipboardText(void *arg)
+static const void *ClipboardDataCallback(void *userdata, const char *mime_type, size_t *length)
 {
-    char *charResult;
-    charResult = SDL_GetClipboardText();
-    SDLTest_AssertPass("Call to SDL_GetClipboardText succeeded");
+    TestClipboardData *test_data = (TestClipboardData *)userdata;
 
-    SDL_free(charResult);
+    ++clipboard_callback_count;
 
-    return TEST_COMPLETED;
+    if (SDL_strcmp(mime_type, test_mime_types[TEST_MIME_TYPE_TEXT]) == 0) {
+        /* We're returning the string "TEST", with no termination */
+        static const char *test_text = "XXX TEST XXX";
+        *length = 4;
+        return test_text + 4;
+    }
+    if (SDL_strcmp(mime_type, test_mime_types[TEST_MIME_TYPE_CUSTOM_TEXT]) == 0) {
+        /* We're returning the string "CUSTOM", with no termination */
+        static const char *custom_text = "XXX CUSTOM XXX";
+        *length = 6;
+        return custom_text + 4;
+    }
+    if (SDL_strcmp(mime_type, test_mime_types[TEST_MIME_TYPE_DATA]) == 0) {
+        *length = test_data->data_size;
+        return test_data->data;
+    }
+    return NULL;
 }
 
-/**
- * \brief Check call to SDL_GetClipboardData
- *
- * \sa SDL_GetClipboardText
- */
-static int clipboard_testGetClipboardData(void *arg)
-{
-    void *buffer = NULL;
-    size_t length;
-    buffer = SDL_GetClipboardData("image/png", &length);
-    SDLTest_AssertPass("Call to SDL_GetClipboardData succeeded");
-
-    if (buffer != NULL) {
-        SDL_free(buffer);
-    }
+static int clipboard_cleanup_count;
 
-    return TEST_COMPLETED;
+static void ClipboardCleanupCallback(void *userdata)
+{
+    ++clipboard_cleanup_count;
 }
 
+/* Test case functions */
+
 /**
- * \brief Check call to SDL_GetPrimarySelectionText
- *
- * \sa SDL_GetPrimarySelectionText
+ * \brief End-to-end test of SDL_xyzClipboardData functions
+ * \sa SDL_HasClipboardData
+ * \sa SDL_GetClipboardData
+ * \sa SDL_SetClipboardData
  */
-static int clipboard_testGetPrimarySelectionText(void *arg)
+static int clipboard_testClipboardDataFunctions(void *arg)
 {
-    char *charResult;
-    charResult = SDL_GetPrimarySelectionText();
-    SDLTest_AssertPass("Call to SDL_GetPrimarySelectionText succeeded");
+    int result = -1;
+    SDL_bool boolResult;
+    int last_clipboard_update_count;
+    int last_clipboard_callback_count;
+    int last_clipboard_cleanup_count;
+    void *data;
+    size_t size;
+    char *text;
+    const char *expected_text;
+
+    TestClipboardData test_data1 = {
+        &test_data1,
+        sizeof(test_data1)
+    };
+    TestClipboardData test_data2 = {
+        &last_clipboard_callback_count,
+        sizeof(last_clipboard_callback_count)
+    };
+
+    SDL_AddEventWatch(ClipboardEventWatch, NULL);
+
+    /* Test clearing clipboard data */
+    result = SDL_ClearClipboardData();
+    SDLTest_AssertCheck(
+        result == 0,
+        "Validate SDL_ClearClipboardData result, expected 0, got %i",
+        result);
 
-    SDL_free(charResult);
+    /* Test clearing clipboard data when it's already clear */
+    last_clipboard_update_count = clipboard_update_count;
+    result = SDL_ClearClipboardData();
+    SDLTest_AssertCheck(
+        result == 0,
+        "Validate SDL_ClearClipboardData result, expected 0, got %i",
+        result);
+    SDLTest_AssertCheck(
+        clipboard_update_count == last_clipboard_update_count,
+        "Verify clipboard update unchanged, got %d",
+        clipboard_update_count - last_clipboard_update_count);
 
-    return TEST_COMPLETED;
-}
+    /* Validate error handling */
+    last_clipboard_update_count = clipboard_update_count;
+    result = SDL_SetClipboardData(NULL, NULL, NULL, test_mime_types, SDL_arraysize(test_mime_types));
+    SDLTest_AssertCheck(
+        result == -1,
+        "Validate SDL_SetClipboardData(invalid) result, expected -1, got %i",
+        result);
+    SDLTest_AssertCheck(
+        clipboard_update_count == last_clipboard_update_count,
+        "Verify clipboard update count unchanged, got %d",
+        clipboard_update_count - last_clipboard_update_count);
 
-/**
- * \brief Check call to SDL_SetClipboardText
- * \sa SDL_SetClipboardText
- */
-static int clipboard_testSetClipboardText(void *arg)
-{
-    char *textRef = SDLTest_RandomAsciiString();
-    char *text = SDL_strdup(textRef);
-    int result;
-    result = SDL_SetClipboardText(text);
-    SDLTest_AssertPass("Call to SDL_SetClipboardText succeeded");
+    last_clipboard_update_count = clipboard_update_count;
+    result = SDL_SetClipboardData(ClipboardDataCallback, ClipboardCleanupCallback, NULL, NULL, 0);
+    SDLTest_AssertCheck(
+        result == -1,
+        "Validate SDL_SetClipboardData(invalid) result, expected -1, got %i",
+        result);
+    SDLTest_AssertCheck(
+        clipboard_update_count == last_clipboard_update_count,
+        "Verify clipboard update count unchanged, got %d",
+        clipboard_update_count - last_clipboard_update_count);
+
+    /* Test setting and getting clipboard data */
+    last_clipboard_update_count = clipboard_update_count;
+    last_clipboard_callback_count = clipboard_callback_count;
+    last_clipboard_cleanup_count = clipboard_cleanup_count;
+    result = SDL_SetClipboardData(ClipboardDataCallback, ClipboardCleanupCallback, &test_data1, test_mime_types, SDL_arraysize(test_mime_types));
     SDLTest_AssertCheck(
         result == 0,
-        "Validate SDL_SetClipboardText result, expected 0, got %i",
+        "Validate SDL_SetClipboardData(test_data1) result, expected 0, got %i",
         result);
     SDLTest_AssertCheck(
-        SDL_strcmp(textRef, text) == 0,
-        "Verify SDL_SetClipboardText did not modify input string, expected '%s', got '%s'",
-        textRef, text);
+        clipboard_update_count == last_clipboard_update_count + 1,
+        "Verify clipboard update count incremented by 1, got %d",
+        clipboard_update_count - last_clipboard_update_count);
+    SDLTest_AssertCheck(
+        clipboard_cleanup_count == last_clipboard_cleanup_count,
+        "Verify clipboard cleanup count unchanged, got %d",
+        clipboard_cleanup_count - last_clipboard_cleanup_count);
 
-    /* Cleanup */
-    SDL_free(textRef);
+    expected_text = "TEST";
+    text = SDL_GetClipboardText();
+    SDLTest_AssertCheck(
+        text && SDL_strcmp(text, expected_text) == 0,
+        "Verify clipboard text, expected \"%s\", got \"%s\"",
+        expected_text, text);
+
+    boolResult = SDL_HasClipboardData(test_mime_types[TEST_MIME_TYPE_TEXT]);
+    SDLTest_AssertCheck(
+        boolResult,
+        "Verify has test text data, expected SDL_TRUE, got SDL_FALSE");
+    text = SDL_GetClipboardData(test_mime_types[TEST_MIME_TYPE_TEXT], &size);
+    SDLTest_AssertCheck(
+        text && text[size] == '\0',
+        "Verify test text data, expected null termination, got %c",
+        text[size]);
+    SDLTest_AssertCheck(
+        text && SDL_strcmp(text, expected_text) == 0,
+        "Verify test text data, expected \"%s\", got \"%s\"",
+        expected_text, text);
+    SDLTest_AssertCheck(
+        size == SDL_strlen(expected_text),
+        "Verify test text size, expected %d, got %d",
+        (int)SDL_strlen(expected_text), (int)size);
     SDL_free(text);
 
-    return TEST_COMPLETED;
-}
+    expected_text = "CUSTOM";
+    boolResult = SDL_HasClipboardData(test_mime_types[TEST_MIME_TYPE_CUSTOM_TEXT]);
+    SDLTest_AssertCheck(
+        boolResult,
+        "Verify has test text data, expected SDL_TRUE, got SDL_FALSE");
+    text = SDL_GetClipboardData(test_mime_types[TEST_MIME_TYPE_CUSTOM_TEXT], &size);
+    SDLTest_AssertCheck(
+        text && text[size] == '\0',
+        "Verify test text data, expected null termination, got %c",
+        text[size]);
+    SDLTest_AssertCheck(
+        text && SDL_strcmp(text, expected_text) == 0,
+        "Verify test text data, expected \"%s\", got \"%s\"",
+        expected_text, text);
+    SDLTest_AssertCheck(
+        size == SDL_strlen(expected_text),
+        "Verify test text size, expected %d, got %d",
+        (int)SDL_strlen(expected_text), (int)size);
+    SDL_free(text);
 
-/**
- * \brief Check call to SDL_SetClipboardData
- * \sa SDL_SetClipboardText
- */
-static int clipboard_testSetClipboardData(void *arg)
-{
-    int result = -1;
+    boolResult = SDL_HasClipboardData(test_mime_types[TEST_MIME_TYPE_DATA]);
+    SDLTest_AssertCheck(
+        boolResult,
+        "Verify has test text data, expected SDL_TRUE, got SDL_FALSE");
+    data = SDL_GetClipboardData(test_mime_types[TEST_MIME_TYPE_DATA], &size);
+    SDLTest_AssertCheck(
+        SDL_memcmp(data, test_data1.data, test_data1.data_size) == 0,
+        "Verify test data");
+    SDLTest_AssertCheck(
+        size == test_data1.data_size,
+        "Verify test data size, expected %d, got %d",
+        (int)test_data1.data_size, (int)size);
+    SDL_free(data);
 
-    result = SDL_SetClipboardData(NULL, NULL, NULL, NULL, 0);
-    SDLTest_AssertPass("Call to SDL_SetClipboardData succeeded");
+    boolResult = SDL_HasClipboardData("test/invalid");
+    SDLTest_AssertCheck(
+        !boolResult,
+        "Verify has test text data, expected SDL_FALSE, got SDL_TRUE");
+    data = SDL_GetClipboardData("test/invalid", &size);
+    SDLTest_AssertCheck(
+        data == NULL,
+        "Verify invalid data, expected NULL, got %p",
+        data);
+    SDLTest_AssertCheck(
+        size == 0,
+        "Verify invalid data size, expected 0, got %d",
+        (int)size);
+    SDL_free(data);
+
+#if 0 /* There's no guarantee how or when the callback is called */
+    SDLTest_AssertCheck(
+        (clipboard_callback_count == last_clipboard_callback_count + 3) ||
+        (clipboard_callback_count == last_clipboard_callback_count + 4),
+        "Verify clipboard callback count incremented by 3 or 4, got %d",
+        clipboard_callback_count - last_clipboard_callback_count);
+#endif
+
+    /* Test setting and getting clipboard data again */
+    last_clipboard_update_count = clipboard_update_count;
+    last_clipboard_callback_count = clipboard_callback_count;
+    last_clipboard_cleanup_count = clipboard_cleanup_count;
+    result = SDL_SetClipboardData(ClipboardDataCallback, ClipboardCleanupCallback, &test_data2, test_mime_types, SDL_arraysize(test_mime_types));
     SDLTest_AssertCheck(
         result == 0,
-        "Validate SDL_SetClipboardData result, expected 0, got %i",
+        "Validate SDL_SetClipboardData(test_data2) result, expected 0, got %i",
         result);
+    SDLTest_AssertCheck(
+        clipboard_update_count == last_clipboard_update_count + 1,
+        "Verify clipboard update count incremented by 1, got %d",
+        clipboard_update_count - last_clipboard_update_count);
+    SDLTest_AssertCheck(
+        clipboard_cleanup_count == last_clipboard_cleanup_count + 1,
+        "Verify clipboard cleanup count incremented by 1, got %d",
+        clipboard_cleanup_count - last_clipboard_cleanup_count);
 
-    return TEST_COMPLETED;
-}
+    expected_text = "TEST";
+    text = SDL_GetClipboardText();
+    SDLTest_AssertCheck(
+        text && SDL_strcmp(text, expected_text) == 0,
+        "Verify clipboard text, expected \"%s\", got \"%s\"",
+        expected_text, text);
 
-/**
- * \brief Check call to SDL_SetPrimarySelectionText
- * \sa SDL_SetPrimarySelectionText
- */
-static int clipboard_testSetPrimarySelectionText(void *arg)
-{
-    char *textRef = SDLTest_RandomAsciiString();
-    char *text = SDL_strdup(textRef);
-    int result;
-    result = SDL_SetPrimarySelectionText(text);
-    SDLTest_AssertPass("Call to SDL_SetPrimarySelectionText succeeded");
+    boolResult = SDL_HasClipboardData(test_mime_types[TEST_MIME_TYPE_TEXT]);
+    SDLTest_AssertCheck(
+        boolResult,
+        "Verify has test text data, expected SDL_TRUE, got SDL_FALSE");
+    text = SDL_GetClipboardData(test_mime_types[TEST_MIME_TYPE_TEXT], &size);
+    SDLTest_AssertCheck(
+        text && text[size] == '\0',
+        "Verify test text data, expected null termination, got %c",
+        text[size]);
+    SDLTest_AssertCheck(
+        text && SDL_strcmp(text, expected_text) == 0,
+        "Verify test text data, expected \"%s\", got \"%s\"",
+        expected_text, text);
+    SDLTest_AssertCheck(
+        size == SDL_strlen(expected_text),
+        "Verify test text size, expected %d, got %d",
+        (int)SDL_strlen(expected_text), (int)size);
+    SDL_free(text);
+
+    expected_text = "CUSTOM";
+    boolResult = SDL_HasClipboardData(test_mime_types[TEST_MIME_TYPE_CUSTOM_TEXT]);
+    SDLTest_AssertCheck(
+        boolResult,
+        "Verify has test text data, expected SDL_TRUE, got SDL_FALSE");
+    text = SDL_GetClipboardData(test_mime_types[TEST_MIME_TYPE_CUSTOM_TEXT], &size);
+    SDLTest_AssertCheck(
+        text && text[size] == '\0',
+        "Verify test text data, expected null termination, got %c",
+        text[size]);
+    SDLTest_AssertCheck(
+        text && SDL_strcmp(text, expected_text) == 0,
+        "Verify test text data, expected \"%s\", got \"%s\"",
+        expected_text, text);
+    SDLTest_AssertCheck(
+        size == SDL_strlen(expected_text),
+        "Verify test text size, expected %d, got %d",
+        (int)SDL_strlen(expected_text), (int)size);
+    SDL_free(text);
+
+    data = SDL_GetClipboardData(test_mime_types[TEST_MIME_TYPE_DATA], &size);
+    SDLTest_AssertCheck(
+        SDL_memcmp(data, test_data2.data, test_data2.data_size) == 0,
+        "Verify test data");
+    SDLTest_AssertCheck(
+        size == test_data2.data_size,
+        "Verify test data size, expected %d, got %d",
+        (int)test_data2.data_size, (int)size);
+    SDL_free(data);
+
+    data = SDL_GetClipboardData("test/invalid", &size);
+    SDLTest_AssertCheck(
+        data == NULL,
+        "Verify invalid data, expected NULL, got %p",
+        data);
+    SDLTest_AssertCheck(
+        size == 0,
+        "Verify invalid data size, expected 0, got %d",
+        (int)size);
+    SDL_free(data);
+
+#if 0 /* There's no guarantee how or when the callback is called */
+    SDLTest_AssertCheck(
+        (clipboard_callback_count == last_clipboard_callback_count + 3) ||
+            (clipboard_callback_count == last_clipboard_callback_count + 4),
+        "Verify clipboard callback count incremented by 3 or 4, got %d",
+        clipboard_callback_count - last_clipboard_callback_count);
+#endif
+
+    /* Test clearing clipboard data when has data */
+    last_clipboard_update_count = clipboard_update_count;
+    last_clipboard_cleanup_count = clipboard_cleanup_count;
+    result = SDL_ClearClipboardData();
     SDLTest_AssertCheck(
         result == 0,
-        "Validate SDL_SetPrimarySelectionText result, expected 0, got %i",
+        "Validate SDL_ClearClipboardData result, expected 0, got %i",
         result);
     SDLTest_AssertCheck(
-        SDL_strcmp(textRef, text) == 0,
-        "Verify SDL_SetPrimarySelectionText did not modify input string, expected '%s', got '%s'",
-        textRef, text);
+        clipboard_update_count == last_clipboard_update_count + 1,
+        "Verify clipboard update count incremented by 1, got %d",
+        clipboard_update_count - last_clipboard_update_count);
+    SDLTest_AssertCheck(
+        clipboard_cleanup_count == last_clipboard_cleanup_count + 1,
+        "Verify clipboard cleanup count incremented by 1, got %d",
+        clipboard_cleanup_count - last_clipboard_cleanup_count);
+    boolResult = SDL_HasClipboardData(test_mime_types[TEST_MIME_TYPE_TEXT]);
+    SDLTest_AssertCheck(
+        !boolResult,
+        "Verify has test text data, expected SDL_FALSE, got SDL_TRUE");
+    boolResult = SDL_HasClipboardData(test_mime_types[TEST_MIME_TYPE_DATA]);
+    SDLTest_AssertCheck(
+        !boolResult,
+        "Verify has test text data, expected SDL_FALSE, got SDL_TRUE");
+    boolResult = SDL_HasClipboardData("test/invalid");
+    SDLTest_AssertCheck(
+        !boolResult,
+        "Verify has test text data, expected SDL_FALSE, got SDL_TRUE");
 
-    /* Cleanup */
-    SDL_free(textRef);
-    SDL_free(text);
+    SDL_DelEventWatch(ClipboardEventWatch, NULL);
 
     return TEST_COMPLETED;
 }
@@ -184,66 +385,73 @@ static int clipboard_testClipboardTextFunctions(void *arg)
     SDL_bool boolResult;
     int intResult;
     char *charResult;
+    int last_clipboard_update_count;
 
-    /* Clear clipboard text state */
-    boolResult = SDL_HasClipboardText();
-    SDLTest_AssertPass("Call to SDL_HasClipboardText succeeded");
-    if (boolResult == SDL_TRUE) {
-        intResult = SDL_SetClipboardText(NULL);
-        SDLTest_AssertPass("Call to SDL_SetClipboardText(NULL) succeeded");
-        SDLTest_AssertCheck(
-            intResult == 0,
-            "Verify result from SDL_SetClipboardText(NULL), expected 0, got %i",
-            intResult);
-        charResult = SDL_GetClipboardText();
-        SDLTest_AssertPass("Call to SDL_GetClipboardText succeeded");
-        SDL_free(charResult);
-        boolResult = SDL_HasClipboardText();
-        SDLTest_AssertPass("Call to SDL_HasClipboardText succeeded");
-        SDLTest_AssertCheck(
-            boolResult == SDL_FALSE,
-            "Verify SDL_HasClipboardText returned SDL_FALSE, got %s",
-            (boolResult) ? "SDL_TRUE" : "SDL_FALSE");
-    }
+    SDL_AddEventWatch(ClipboardEventWatch, NULL);
 
-    /* Empty clipboard  */
+    /* Empty clipboard text */
+    last_clipboard_update_count = clipboard_update_count;
+    intResult = SDL_SetClipboardText(NULL);
+    SDLTest_AssertCheck(
+        intResult == 0,
+        "Verify result from SDL_SetClipboardText(NULL), expected 0, got %i",
+        intResult);
     charResult = SDL_GetClipboardText();
-    SDLTest_AssertPass("Call to SDL_GetClipboardText succeeded");
-    SDLTest_Assert(
-        charResult != NULL,
-        "Verify SDL_GetClipboardText did not return NULL");
-    SDLTest_AssertCheck(
-        charResult[0] == '\0', /* NOLINT(clang-analyzer-core.NullDereference): Checked for NULL above */
-        "Verify SDL_GetClipboardText returned string with length 0, got length %i",
-        (int)SDL_strlen(charResult));
+    SDLTest_AssertCheck(
+        charResult && SDL_strcmp(charResult, "") == 0,
+        "Verify SDL_GetClipboardText returned \"\", got %s",
+        charResult);
+    SDL_free(charResult);
+    boolResult = SDL_HasClipboardText();
+    SDLTest_AssertCheck(
+        boolResult == SDL_FALSE,
+        "Verify SDL_HasClipboardText returned SDL_FALSE, got %s",
+        (boolResult) ? "SDL_TRUE" : "SDL_FALSE");
+    SDLTest_AssertCheck(
+        clipboard_update_count == last_clipboard_update_count,
+        "Verify clipboard update unchanged, got %d",
+        clipboard_update_count - last_clipboard_update_count);
+
+
+    /* Set clipboard text  */
+    last_clipboard_update_count = clipboard_update_count;
     intResult = SDL_SetClipboardText(text);
-    SDLTest_AssertPass("Call to SDL_SetClipboardText succeeded");
     SDLTest_AssertCheck(
         intResult == 0,
-        "Verify result from SDL_SetClipboardText(NULL), expected 0, got %i",
+        "Verify result from SDL_SetClipboardText(%s), expected 0, got %i", text,
         intResult);
     SDLTest_AssertCheck(
         SDL_strcmp(textRef, text) == 0,
         "Verify SDL_SetClipboardText did not modify input string, expected '%s', got '%s'",
         textRef, text);
     boolResult = SDL_HasClipboardText();
-    SDLTest_AssertPass("Call to SDL_HasClipboardText succeeded");
     SDLTest_AssertCheck(
         boolResult == SDL_TRUE,
         "Verify SDL_HasClipboardText returned SDL_TRUE, got %s",
         (boolResult) ? "SDL_TRUE" : "SDL_FALSE");
-    SDL_free(charResult);
     charResult = SDL_GetClipboardText();
-    SDLTest_AssertPass("Call to SDL_GetClipboardText succeeded");
     SDLTest_AssertCheck(
-        SDL_strcmp(textRef, charResult) == 0,
+        charResult && SDL_strcmp(textRef, charResult) == 0,
         "Verify SDL_GetClipboardText returned correct string, expected '%s', got '%s'",
         textRef, charResult);
+    SDL_free(charResult);
+    SDLTest_AssertCheck(
+        clipboard_update_count == last_clipboard_update_count + 1,
+        "Verify clipboard update count incremented by 1, got %d",
+        clipboard_update_count - last_clipboard_update_count);
+
+    /* Reset clipboard text */
+    intResult = SDL_SetClipboardText(NULL);
+    SDLTest_AssertCheck(
+        intResult == 0,
+        "Verify result from SDL_SetClipboardText(NULL), expected 0, got %i",
+        intResult);
 
     /* Cleanup */
     SDL_free(textRef);
     SDL_free(text);
-    SDL_free(charResult);
+
+    SDL_DelEventWatch(ClipboardEventWatch, NULL);
 
     return TEST_COMPLETED;
 }
@@ -261,120 +469,93 @@ static int clipboard_testPrimarySelectionTextFunctions(void *arg)
     SDL_bool boolResult;
     int intResult;
     char *charResult;
+    int last_clipboard_update_count;
 
-    /* Clear primary selection text state */
-    boolResult = SDL_HasPrimarySelectionText();
-    SDLTest_AssertPass("Call to SDL_HasPrimarySelectionText succeeded");
-    if (boolResult == SDL_TRUE) {
-        intResult = SDL_SetPrimarySelectionText(NULL);
-        SDLTest_AssertPass("Call to SDL_SetPrimarySelectionText(NULL) succeeded");
-        SDLTest_AssertCheck(
-            intResult == 0,
-            "Verify result from SDL_SetPrimarySelectionText(NULL), expected 0, got %i",
-            intResult);
-        charResult = SDL_GetPrimarySelectionText();
-        SDLTest_AssertPass("Call to SDL_GetPrimarySelectionText succeeded");
-        SDL_free(charResult);
-        boolResult = SDL_HasPrimarySelectionText();
-        SDLTest_AssertPass("Call to SDL_HasPrimarySelectionText succeeded");
-        SDLTest_AssertCheck(
-            boolResult == SDL_FALSE,
-            "Verify SDL_HasPrimarySelectionText returned SDL_FALSE, got %s",
-            (boolResult) ? "SDL_TRUE" : "SDL_FALSE");
-    }
+    SDL_AddEventWatch(ClipboardEventWatch, NULL);
 
-    /* Empty primary selection  */
+    /* Empty primary selection */
+    last_clipboard_update_count = clipboard_update_count;
+    intResult = SDL_SetPrimarySelectionText(NULL);
+    SDLTest_AssertCheck(
+        intResult == 0,
+        "Verify result from SDL_SetPrimarySelectionText(NULL), expected 0, got %i",
+        intResult);
     charResult = SDL_GetPrimarySelectionText();
-    SDLTest_AssertPass("Call to SDL_GetPrimarySelectionText succeeded");
-    SDLTest_Assert(
-        charResult != NULL,
-        "Verify SDL_GetPrimarySelectionText did not return NULL");
-    SDLTest_AssertCheck(
-        charResult[0] == '\0', /* NOLINT(clang-analyzer-core.NullDereference): Checked for NULL above */
-        "Verify SDL_GetPrimarySelectionText returned string with length 0, got length %i",
-        (int)SDL_strlen(charResult));
+    SDLTest_AssertCheck(
+        charResult && SDL_strcmp(charResult, "") == 0,
+        "Verify SDL_GetPrimarySelectionText returned \"\", got %s",
+        charResult);
+    SDL_free(charResult);
+    boolResult = SDL_HasPrimarySelectionText();
+    SDLTest_AssertCheck(
+        boolResult == SDL_FALSE,
+        "Verify SDL_HasPrimarySelectionText returned SDL_FALSE, got %s",
+        (boolResult) ? "SDL_TRUE" : "SDL_FALSE");
+    SDLTest_AssertCheck(
+        clipboard_update_count == last_clipboard_update_count + 1,
+        "Verify clipboard update count incremented by 1, got %d",
+        clipboard_update_count - last_clipboard_update_count);
+
+    /* Set primary selection  */
+    last_clipboard_update_count = clipboard_update_count;
     intResult = SDL_SetPrimarySelectionText(text);
-    SDLTest_AssertPass("Call to SDL_SetPrimarySelectionText succeeded");
     SDLTest_AssertCheck(
         intResult == 0,
-        "Verify result from SDL_SetPrimarySelectionText(NULL), expected 0, got %i",
+        "Verify result from SDL_SetPrimarySelectionText(%s), expected 0, got %i", text,
         intResult);
     SDLTest_AssertCheck(
         SDL_strcmp(textRef, text) == 0,
         "Verify SDL_SetPrimarySelectionText did not modify input string, expected '%s', got '%s'",
         textRef, text);
     boolResult = SDL_HasPrimarySelectionText();
-    SDLTest_AssertPass("Call to SDL_HasPrimarySelectionText succeeded");
     SDLTest_AssertCheck(
         boolResult == SDL_TRUE,
         "Verify SDL_HasPrimarySelectionText returned SDL_TRUE, got %s",
         (boolResult) ? "SDL_TRUE" : "SDL_FALSE");
-    SDL_free(charResult);
     charResult = SDL_GetPrimarySelectionText();
-    SDLTest_AssertPass("Call to SDL_GetPrimarySelectionText succeeded");
     SDLTest_AssertCheck(
-        SDL_strcmp(textRef, charResult) == 0,
+        charResult && SDL_strcmp(textRef, charResult) == 0,
         "Verify SDL_GetPrimarySelectionText returned correct string, expected '%s', got '%s'",
         textRef, charResult);
+    SDL_free(charResult);
+    SDLTest_AssertCheck(
+        clipboard_update_count == last_clipboard_update_count + 1,
+        "Verify clipboard update count incremented by 1, got %d",
+        clipboard_update_count - last_clipboard_update_count);
+
+    /* Reset primary selection */
+    intResult = SDL_SetPrimarySelectionText(NULL);
+    SDLTest_AssertCheck(
+        intResult == 0,
+        "Verify result from SDL_SetPrimarySelectionText(NULL), expected 0, got %i",
+        intResult);
 
     /* Cleanup */
     SDL_free(textRef);
     SDL_free(text);
-    SDL_free(charResult);
+
+    SDL_DelEventWatch(ClipboardEventWatch, NULL);
 
     return TEST_COMPLETED;
 }
 
 /* ================= Test References ================== */
 
-/* Clipboard test cases */
 static const SDLTest_TestCaseReference clipboardTest1 = {
-    (SDLTest_TestCaseFp)clipboard_testHasClipboardText, "clipboard_testHasClipboardText", "Check call to SDL_HasClipboardText", TEST_ENABLED
+    (SDLTest_TestCaseFp)clipboard_testClipboardDataFunctions, "clipboard_testClipboardDataFunctions", "End-to-end test of SDL_xyzClipboardData functions", TEST_ENABLED
 };
 
 static const SDLTest_TestCaseReference clipboardTest2 = {
-    (SDLTest_TestCaseFp)clipboard_testHasPrimarySelectionText, "clipboard_testHasPrimarySelectionText", "Check call to SDL_HasPrimarySelectionText", TEST_ENABLED
-};
-
-static const SDLTest_TestCaseReference clipboardTest3 = {
-    (SDLTest_TestCaseFp)clipboard_testGetClipboardText, "clipboard_testGetClipboardText", "Check call to SDL_GetClipboardText", TEST_ENABLED
-};
-
-static const SDLTest_TestCaseReference clipboardTest4 = {
-    (SDLTest_TestCaseFp)clipboard_testGetPrimarySelectionText, "clipboard_testGetPrimarySelectionText", "Check call to SDL_GetPrimarySelectionText", TEST_ENABLED
-};
-
-static const SDLTest_TestCaseReference clipboardTest5 = {
-    (SDLTest_TestCaseFp)clipboard_testSetClipboardText, "clipboard_testSetClipboardText", "Check call to SDL_SetClipboardText", TEST_ENABLED
-};
-
-static const SDLTest_TestCaseReference clipboardTest6 = {
-    (SDLTest_TestCaseFp)clipboard_testSetPrimarySelectionText, "clipboard_testSetPrimarySelectionText", "Check call to SDL_SetPrimarySelectionText", TEST_ENABLED
-};
-
-static const SDLTest_TestCaseReference clipboardTest7 = {
     (SDLTest_TestCaseFp)clipboard_testClipboardTextFunctions, "clipboard_testClipboardTextFunctions", "End-to-end test of SDL_xyzClipboardText functions", TEST_ENABLED
 };
 
-static const SDLTest_TestCaseReference clipboardTest8 = {
+static const SDLTest_TestCaseReference clipboardTest3 = {
     (SDLTest_TestCaseFp)clipboard_testPrimarySelectionTextFunctions, "clipboard_testPrimarySelectionTextFunctions", "End-to-end test of SDL_xyzPrimarySelectionText functions", TEST_ENABLED
 };
 
-static const SDLTest_TestCaseReference clipboardTest9 = {
-    (SDLTest_TestCaseFp)clipboard_testGetClipboardData, "clipboard_testGetClipboardData", "Check call to SDL_GetClipboardData", TEST_ENABLED
-};
-
-static const SDLTest_TestCaseReference clipboardTest10 = {
-    (SDLTest_TestCaseFp)clipboard_testSetClipboardData, "clipboard_testSetClipboardData", "Check call to SDL_SetClipboardData", TEST_ENABLED
-};
-
-static const SDLTest_TestCaseReference clipboardTest11 = {
-    (SDLTest_TestCaseFp)clipboard_testHasClipboardData, "clipboard_testHasClipboardData", "Check call to SDL_HasClipboardData", TEST_ENABLED
-};
-
 /* Sequence of Clipboard test cases */
 static const SDLTest_TestCaseReference *clipboardTests[] = {
-    &clipboardTest1, &clipboardTest2, &clipboardTest3, &clipboardTest4, &clipboardTest5, &clipboardTest6, &clipboardTest7, &clipboardTest8, &clipboardTest9, &clipboardTest10, &clipboardTest11, NULL
+    &clipboardTest1, &clipboardTest2, &clipboardTest3,  NULL
 };
 
 /* Clipboard test suite (global) */

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