diff options
Diffstat (limited to 'contrib/SDL-3.2.8/test/testautomation_events.c')
| -rw-r--r-- | contrib/SDL-3.2.8/test/testautomation_events.c | 341 |
1 files changed, 341 insertions, 0 deletions
diff --git a/contrib/SDL-3.2.8/test/testautomation_events.c b/contrib/SDL-3.2.8/test/testautomation_events.c new file mode 100644 index 0000000..ed4e684 --- /dev/null +++ b/contrib/SDL-3.2.8/test/testautomation_events.c | |||
| @@ -0,0 +1,341 @@ | |||
| 1 | /** | ||
| 2 | * Events test suite | ||
| 3 | */ | ||
| 4 | #include <SDL3/SDL.h> | ||
| 5 | #include <SDL3/SDL_test.h> | ||
| 6 | #include "testautomation_suites.h" | ||
| 7 | |||
| 8 | /* ================= Test Case Implementation ================== */ | ||
| 9 | |||
| 10 | /* Test case functions */ | ||
| 11 | |||
| 12 | /* Flag indicating if the userdata should be checked */ | ||
| 13 | static int g_userdataCheck = 0; | ||
| 14 | |||
| 15 | /* Userdata value to check */ | ||
| 16 | static int g_userdataValue = 0; | ||
| 17 | |||
| 18 | /* Flag indicating that the filter was called */ | ||
| 19 | static int g_eventFilterCalled = 0; | ||
| 20 | |||
| 21 | /* Userdata values for event */ | ||
| 22 | static int g_userdataValue1 = 1; | ||
| 23 | static int g_userdataValue2 = 2; | ||
| 24 | |||
| 25 | #define MAX_ITERATIONS 100 | ||
| 26 | |||
| 27 | /* Event filter that sets some flags and optionally checks userdata */ | ||
| 28 | static bool SDLCALL events_sampleNullEventFilter(void *userdata, SDL_Event *event) | ||
| 29 | { | ||
| 30 | g_eventFilterCalled = 1; | ||
| 31 | |||
| 32 | if (g_userdataCheck != 0) { | ||
| 33 | SDLTest_AssertCheck(userdata != NULL, "Check userdata pointer, expected: non-NULL, got: %s", (userdata != NULL) ? "non-NULL" : "NULL"); | ||
| 34 | if (userdata != NULL) { | ||
| 35 | SDLTest_AssertCheck(*(int *)userdata == g_userdataValue, "Check userdata value, expected: %i, got: %i", g_userdataValue, *(int *)userdata); | ||
| 36 | } | ||
| 37 | } | ||
| 38 | |||
| 39 | return true; | ||
| 40 | } | ||
| 41 | |||
| 42 | /** | ||
| 43 | * Test pumping and peeking events. | ||
| 44 | * | ||
| 45 | * \sa SDL_PumpEvents | ||
| 46 | * \sa SDL_PollEvent | ||
| 47 | */ | ||
| 48 | static int SDLCALL events_pushPumpAndPollUserevent(void *arg) | ||
| 49 | { | ||
| 50 | SDL_Event event_in; | ||
| 51 | SDL_Event event_out; | ||
| 52 | int result; | ||
| 53 | int i; | ||
| 54 | Sint32 ref_code = SDLTest_RandomSint32(); | ||
| 55 | SDL_Window *event_window; | ||
| 56 | |||
| 57 | /* Flush all events */ | ||
| 58 | SDL_FlushEvents(SDL_EVENT_FIRST, SDL_EVENT_LAST); | ||
| 59 | SDLTest_AssertCheck(!SDL_HasEvents(SDL_EVENT_USER, SDL_EVENT_USER), "Check SDL_HasEvents returns false"); | ||
| 60 | |||
| 61 | /* Create user event */ | ||
| 62 | event_in.type = SDL_EVENT_USER; | ||
| 63 | event_in.user.windowID = 0; | ||
| 64 | event_in.common.timestamp = 0; | ||
| 65 | event_in.user.code = ref_code; | ||
| 66 | event_in.user.data1 = (void *)&g_userdataValue1; | ||
| 67 | event_in.user.data2 = (void *)&g_userdataValue2; | ||
| 68 | |||
| 69 | /* Push a user event onto the queue and force queue update */ | ||
| 70 | SDL_PushEvent(&event_in); | ||
| 71 | SDLTest_AssertPass("Call to SDL_PushEvent()"); | ||
| 72 | SDL_PumpEvents(); | ||
| 73 | SDLTest_AssertPass("Call to SDL_PumpEvents()"); | ||
| 74 | |||
| 75 | SDLTest_AssertCheck(SDL_HasEvents(SDL_EVENT_USER, SDL_EVENT_USER), "Check SDL_HasEvents returns true"); | ||
| 76 | |||
| 77 | /* Poll until we get a user event. */ | ||
| 78 | for (i = 0; i < MAX_ITERATIONS; i++) { | ||
| 79 | result = SDL_PollEvent(&event_out); | ||
| 80 | SDLTest_AssertPass("Call to SDL_PollEvent()"); | ||
| 81 | SDLTest_AssertCheck(result == 1, "Check result from SDL_PollEvent, expected: 1, got: %d", result); | ||
| 82 | if (!result) { | ||
| 83 | break; | ||
| 84 | } | ||
| 85 | if (event_out.type == SDL_EVENT_USER) { | ||
| 86 | break; | ||
| 87 | } | ||
| 88 | } | ||
| 89 | SDLTest_AssertCheck(i < MAX_ITERATIONS, "Check the user event is seen in less then %d polls, got %d poll", MAX_ITERATIONS, i + 1); | ||
| 90 | |||
| 91 | SDLTest_AssertCheck(SDL_EVENT_USER == event_out.type, "Check event type is SDL_EVENT_USER, expected: 0x%x, got: 0x%" SDL_PRIx32, SDL_EVENT_USER, event_out.type); | ||
| 92 | SDLTest_AssertCheck(ref_code == event_out.user.code, "Check SDL_Event.user.code, expected: 0x%" SDL_PRIx32 ", got: 0x%" SDL_PRIx32 , ref_code, event_out.user.code); | ||
| 93 | SDLTest_AssertCheck(0 == event_out.user.windowID, "Check SDL_Event.user.windowID, expected: NULL , got: %" SDL_PRIu32, event_out.user.windowID); | ||
| 94 | SDLTest_AssertCheck((void *)&g_userdataValue1 == event_out.user.data1, "Check SDL_Event.user.data1, expected: %p, got: %p", &g_userdataValue1, event_out.user.data1); | ||
| 95 | SDLTest_AssertCheck((void *)&g_userdataValue2 == event_out.user.data2, "Check SDL_Event.user.data2, expected: %p, got: %p", &g_userdataValue2, event_out.user.data2); | ||
| 96 | event_window = SDL_GetWindowFromEvent(&event_out); | ||
| 97 | SDLTest_AssertCheck(NULL == SDL_GetWindowFromEvent(&event_out), "Check SDL_GetWindowFromEvent returns the window id from a user event, expected: NULL, got: %p", event_window); | ||
| 98 | |||
| 99 | /* Need to finish getting all events and sentinel, otherwise other tests that rely on event are in bad state */ | ||
| 100 | SDL_FlushEvents(SDL_EVENT_FIRST, SDL_EVENT_LAST); | ||
| 101 | |||
| 102 | return TEST_COMPLETED; | ||
| 103 | } | ||
| 104 | |||
| 105 | /** | ||
| 106 | * Adds and deletes an event watch function with NULL userdata | ||
| 107 | * | ||
| 108 | * \sa SDL_AddEventWatch | ||
| 109 | * \sa SDL_RemoveEventWatch | ||
| 110 | * | ||
| 111 | */ | ||
| 112 | static int SDLCALL events_addDelEventWatch(void *arg) | ||
| 113 | { | ||
| 114 | SDL_Event event; | ||
| 115 | |||
| 116 | /* Create user event */ | ||
| 117 | event.type = SDL_EVENT_USER; | ||
| 118 | event.common.timestamp = 0; | ||
| 119 | event.user.code = SDLTest_RandomSint32(); | ||
| 120 | event.user.data1 = (void *)&g_userdataValue1; | ||
| 121 | event.user.data2 = (void *)&g_userdataValue2; | ||
| 122 | |||
| 123 | /* Disable userdata check */ | ||
| 124 | g_userdataCheck = 0; | ||
| 125 | |||
| 126 | /* Reset event filter call tracker */ | ||
| 127 | g_eventFilterCalled = 0; | ||
| 128 | |||
| 129 | /* Add watch */ | ||
| 130 | SDL_AddEventWatch(events_sampleNullEventFilter, NULL); | ||
| 131 | SDLTest_AssertPass("Call to SDL_AddEventWatch()"); | ||
| 132 | |||
| 133 | /* Push a user event onto the queue and force queue update */ | ||
| 134 | SDL_PushEvent(&event); | ||
| 135 | SDLTest_AssertPass("Call to SDL_PushEvent()"); | ||
| 136 | SDL_PumpEvents(); | ||
| 137 | SDLTest_AssertPass("Call to SDL_PumpEvents()"); | ||
| 138 | SDLTest_AssertCheck(g_eventFilterCalled == 1, "Check that event filter was called"); | ||
| 139 | |||
| 140 | /* Delete watch */ | ||
| 141 | SDL_RemoveEventWatch(events_sampleNullEventFilter, NULL); | ||
| 142 | SDLTest_AssertPass("Call to SDL_RemoveEventWatch()"); | ||
| 143 | |||
| 144 | /* Push a user event onto the queue and force queue update */ | ||
| 145 | g_eventFilterCalled = 0; | ||
| 146 | SDL_PushEvent(&event); | ||
| 147 | SDLTest_AssertPass("Call to SDL_PushEvent()"); | ||
| 148 | SDL_PumpEvents(); | ||
| 149 | SDLTest_AssertPass("Call to SDL_PumpEvents()"); | ||
| 150 | SDLTest_AssertCheck(g_eventFilterCalled == 0, "Check that event filter was NOT called"); | ||
| 151 | |||
| 152 | return TEST_COMPLETED; | ||
| 153 | } | ||
| 154 | |||
| 155 | /** | ||
| 156 | * Adds and deletes an event watch function with userdata | ||
| 157 | * | ||
| 158 | * \sa SDL_AddEventWatch | ||
| 159 | * \sa SDL_RemoveEventWatch | ||
| 160 | * | ||
| 161 | */ | ||
| 162 | static int SDLCALL events_addDelEventWatchWithUserdata(void *arg) | ||
| 163 | { | ||
| 164 | SDL_Event event; | ||
| 165 | |||
| 166 | /* Create user event */ | ||
| 167 | event.type = SDL_EVENT_USER; | ||
| 168 | event.common.timestamp = 0; | ||
| 169 | event.user.code = SDLTest_RandomSint32(); | ||
| 170 | event.user.data1 = (void *)&g_userdataValue1; | ||
| 171 | event.user.data2 = (void *)&g_userdataValue2; | ||
| 172 | |||
| 173 | /* Enable userdata check and set a value to check */ | ||
| 174 | g_userdataCheck = 1; | ||
| 175 | g_userdataValue = SDLTest_RandomIntegerInRange(-1024, 1024); | ||
| 176 | |||
| 177 | /* Reset event filter call tracker */ | ||
| 178 | g_eventFilterCalled = 0; | ||
| 179 | |||
| 180 | /* Add watch */ | ||
| 181 | SDL_AddEventWatch(events_sampleNullEventFilter, (void *)&g_userdataValue); | ||
| 182 | SDLTest_AssertPass("Call to SDL_AddEventWatch()"); | ||
| 183 | |||
| 184 | /* Push a user event onto the queue and force queue update */ | ||
| 185 | SDL_PushEvent(&event); | ||
| 186 | SDLTest_AssertPass("Call to SDL_PushEvent()"); | ||
| 187 | SDL_PumpEvents(); | ||
| 188 | SDLTest_AssertPass("Call to SDL_PumpEvents()"); | ||
| 189 | SDLTest_AssertCheck(g_eventFilterCalled == 1, "Check that event filter was called"); | ||
| 190 | |||
| 191 | /* Delete watch */ | ||
| 192 | SDL_RemoveEventWatch(events_sampleNullEventFilter, (void *)&g_userdataValue); | ||
| 193 | SDLTest_AssertPass("Call to SDL_RemoveEventWatch()"); | ||
| 194 | |||
| 195 | /* Push a user event onto the queue and force queue update */ | ||
| 196 | g_eventFilterCalled = 0; | ||
| 197 | SDL_PushEvent(&event); | ||
| 198 | SDLTest_AssertPass("Call to SDL_PushEvent()"); | ||
| 199 | SDL_PumpEvents(); | ||
| 200 | SDLTest_AssertPass("Call to SDL_PumpEvents()"); | ||
| 201 | SDLTest_AssertCheck(g_eventFilterCalled == 0, "Check that event filter was NOT called"); | ||
| 202 | |||
| 203 | return TEST_COMPLETED; | ||
| 204 | } | ||
| 205 | |||
| 206 | /** | ||
| 207 | * Runs callbacks on the main thread. | ||
| 208 | * | ||
| 209 | * \sa SDL_IsMainThread | ||
| 210 | * \sa SDL_RunOnMainThread | ||
| 211 | * | ||
| 212 | */ | ||
| 213 | |||
| 214 | typedef struct IncrementCounterData_t | ||
| 215 | { | ||
| 216 | Uint32 delay; | ||
| 217 | int counter; | ||
| 218 | } IncrementCounterData_t; | ||
| 219 | |||
| 220 | static void SDLCALL IncrementCounter(void *userdata) | ||
| 221 | { | ||
| 222 | IncrementCounterData_t *data = (IncrementCounterData_t *)userdata; | ||
| 223 | ++data->counter; | ||
| 224 | } | ||
| 225 | |||
| 226 | #ifndef SDL_PLATFORM_EMSCRIPTEN /* Emscripten doesn't have threads */ | ||
| 227 | static int SDLCALL IncrementCounterThread(void *userdata) | ||
| 228 | { | ||
| 229 | IncrementCounterData_t *data = (IncrementCounterData_t *)userdata; | ||
| 230 | SDL_Event event; | ||
| 231 | |||
| 232 | SDL_assert(!SDL_IsMainThread()); | ||
| 233 | |||
| 234 | if (data->delay > 0) { | ||
| 235 | SDL_Delay(data->delay); | ||
| 236 | } | ||
| 237 | |||
| 238 | if (!SDL_RunOnMainThread(IncrementCounter, userdata, false)) { | ||
| 239 | SDLTest_LogError("Couldn't run IncrementCounter asynchronously on main thread: %s", SDL_GetError()); | ||
| 240 | } | ||
| 241 | if (!SDL_RunOnMainThread(IncrementCounter, userdata, true)) { | ||
| 242 | SDLTest_LogError("Couldn't run IncrementCounter synchronously on main thread: %s", SDL_GetError()); | ||
| 243 | } | ||
| 244 | |||
| 245 | /* Send an event to unblock the main thread, which is waiting in SDL_WaitEvent() */ | ||
| 246 | event.type = SDL_EVENT_USER; | ||
| 247 | SDL_PushEvent(&event); | ||
| 248 | |||
| 249 | return 0; | ||
| 250 | } | ||
| 251 | #endif /* !SDL_PLATFORM_EMSCRIPTEN */ | ||
| 252 | |||
| 253 | static int SDLCALL events_mainThreadCallbacks(void *arg) | ||
| 254 | { | ||
| 255 | IncrementCounterData_t data = { 0, 0 }; | ||
| 256 | |||
| 257 | /* Make sure we're on the main thread */ | ||
| 258 | SDLTest_AssertCheck(SDL_IsMainThread(), "Verify we're on the main thread"); | ||
| 259 | |||
| 260 | SDL_RunOnMainThread(IncrementCounter, &data, true); | ||
| 261 | SDLTest_AssertCheck(data.counter == 1, "Incremented counter on main thread, expected 1, got %d", data.counter); | ||
| 262 | |||
| 263 | #ifndef SDL_PLATFORM_EMSCRIPTEN /* Emscripten doesn't have threads */ | ||
| 264 | { | ||
| 265 | SDL_Window *window; | ||
| 266 | SDL_Thread *thread; | ||
| 267 | SDL_Event event; | ||
| 268 | |||
| 269 | window = SDL_CreateWindow("test", 0, 0, SDL_WINDOW_HIDDEN); | ||
| 270 | SDLTest_AssertCheck(window != NULL, "Create window, expected non-NULL, got %p", window); | ||
| 271 | |||
| 272 | /* Flush any pending events */ | ||
| 273 | SDL_PumpEvents(); | ||
| 274 | SDL_FlushEvents(SDL_EVENT_FIRST, SDL_EVENT_LAST); | ||
| 275 | |||
| 276 | /* Increment the counter on a thread, waiting for both calls to be queued */ | ||
| 277 | thread = SDL_CreateThread(IncrementCounterThread, NULL, &data); | ||
| 278 | SDLTest_AssertCheck(thread != NULL, "Create counter thread"); | ||
| 279 | |||
| 280 | /* Wait for both increment calls to be queued up */ | ||
| 281 | SDL_Delay(100); | ||
| 282 | |||
| 283 | /* Run the main callbacks */ | ||
| 284 | SDL_WaitEvent(&event); | ||
| 285 | SDLTest_AssertCheck(event.type == SDL_EVENT_USER, "Expected user event (0x%.4x), got 0x%.4x", SDL_EVENT_USER, (int)event.type); | ||
| 286 | SDL_WaitThread(thread, NULL); | ||
| 287 | SDLTest_AssertCheck(data.counter == 3, "Incremented counter on main thread, expected 3, got %d", data.counter); | ||
| 288 | |||
| 289 | /* Try again, but this time delay the calls until we've started waiting for events */ | ||
| 290 | data.delay = 100; | ||
| 291 | thread = SDL_CreateThread(IncrementCounterThread, NULL, &data); | ||
| 292 | SDLTest_AssertCheck(thread != NULL, "Create counter thread"); | ||
| 293 | |||
| 294 | /* Run the main callbacks */ | ||
| 295 | SDL_WaitEvent(&event); | ||
| 296 | SDLTest_AssertCheck(event.type == SDL_EVENT_USER, "Expected user event (0x%.4x), got 0x%.4x", SDL_EVENT_USER, (int)event.type); | ||
| 297 | SDL_WaitThread(thread, NULL); | ||
| 298 | SDLTest_AssertCheck(data.counter == 5, "Incremented counter on main thread, expected 5, got %d", data.counter); | ||
| 299 | |||
| 300 | SDL_DestroyWindow(window); | ||
| 301 | } | ||
| 302 | #endif /* !SDL_PLATFORM_EMSCRIPTEN */ | ||
| 303 | |||
| 304 | return TEST_COMPLETED; | ||
| 305 | } | ||
| 306 | |||
| 307 | /* ================= Test References ================== */ | ||
| 308 | |||
| 309 | /* Events test cases */ | ||
| 310 | static const SDLTest_TestCaseReference eventsTest_pushPumpAndPollUserevent = { | ||
| 311 | events_pushPumpAndPollUserevent, "events_pushPumpAndPollUserevent", "Pushes, pumps and polls a user event", TEST_ENABLED | ||
| 312 | }; | ||
| 313 | |||
| 314 | static const SDLTest_TestCaseReference eventsTest_addDelEventWatch = { | ||
| 315 | events_addDelEventWatch, "events_addDelEventWatch", "Adds and deletes an event watch function with NULL userdata", TEST_ENABLED | ||
| 316 | }; | ||
| 317 | |||
| 318 | static const SDLTest_TestCaseReference eventsTest_addDelEventWatchWithUserdata = { | ||
| 319 | events_addDelEventWatchWithUserdata, "events_addDelEventWatchWithUserdata", "Adds and deletes an event watch function with userdata", TEST_ENABLED | ||
| 320 | }; | ||
| 321 | |||
| 322 | static const SDLTest_TestCaseReference eventsTest_mainThreadCallbacks = { | ||
| 323 | events_mainThreadCallbacks, "events_mainThreadCallbacks", "Run callbacks on the main thread", TEST_ENABLED | ||
| 324 | }; | ||
| 325 | |||
| 326 | /* Sequence of Events test cases */ | ||
| 327 | static const SDLTest_TestCaseReference *eventsTests[] = { | ||
| 328 | &eventsTest_pushPumpAndPollUserevent, | ||
| 329 | &eventsTest_addDelEventWatch, | ||
| 330 | &eventsTest_addDelEventWatchWithUserdata, | ||
| 331 | &eventsTest_mainThreadCallbacks, | ||
| 332 | NULL | ||
| 333 | }; | ||
| 334 | |||
| 335 | /* Events test suite (global) */ | ||
| 336 | SDLTest_TestSuiteReference eventsTestSuite = { | ||
| 337 | "Events", | ||
| 338 | NULL, | ||
| 339 | eventsTests, | ||
| 340 | NULL | ||
| 341 | }; | ||
