1
0

testautomation_events.c 12 KB

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