user32/tests: Add a test for sending inter-thread messages.
This commit is contained in:
parent
b24ce98af3
commit
4ae80d15d9
|
@ -14598,6 +14598,153 @@ static void test_TrackPopupMenuEmpty(void)
|
||||||
DestroyWindow(hwnd);
|
DestroyWindow(hwnd);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static const struct message send_message_1[] = {
|
||||||
|
{ WM_USER+2, sent|wparam|lparam, 0, 0 },
|
||||||
|
{ WM_USER, sent|wparam|lparam, 0, 0 },
|
||||||
|
{ 0 }
|
||||||
|
};
|
||||||
|
static const struct message send_message_2[] = {
|
||||||
|
{ WM_USER+4, sent|wparam|lparam, 0, 0 },
|
||||||
|
{ 0 }
|
||||||
|
};
|
||||||
|
static const struct message send_message_3[] = {
|
||||||
|
{ WM_USER+3, sent|wparam|lparam, 0, 0 },
|
||||||
|
{ WM_USER+1, sent|wparam|lparam, 0, 0 },
|
||||||
|
{ 0 }
|
||||||
|
};
|
||||||
|
|
||||||
|
static DWORD WINAPI SendMessage_thread_1(void *param)
|
||||||
|
{
|
||||||
|
struct wnd_event *wnd_event = param;
|
||||||
|
|
||||||
|
trace("thread: starting\n");
|
||||||
|
WaitForSingleObject(wnd_event->start_event, INFINITE);
|
||||||
|
|
||||||
|
trace("thread: call PostMessage\n");
|
||||||
|
PostMessageA(wnd_event->hwnd, WM_USER, 0, 0);
|
||||||
|
|
||||||
|
trace("thread: call PostMessage\n");
|
||||||
|
PostMessageA(wnd_event->hwnd, WM_USER+1, 0, 0);
|
||||||
|
|
||||||
|
trace("thread: call SendMessage\n");
|
||||||
|
SendMessageA(wnd_event->hwnd, WM_USER+2, 0, 0);
|
||||||
|
|
||||||
|
trace("thread: call SendMessage\n");
|
||||||
|
SendMessageA(wnd_event->hwnd, WM_USER+3, 0, 0);
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static DWORD WINAPI SendMessage_thread_2(void *param)
|
||||||
|
{
|
||||||
|
struct wnd_event *wnd_event = param;
|
||||||
|
|
||||||
|
trace("thread: starting\n");
|
||||||
|
WaitForSingleObject(wnd_event->start_event, INFINITE);
|
||||||
|
|
||||||
|
trace("thread: call PostMessage\n");
|
||||||
|
PostMessageA(wnd_event->hwnd, WM_USER, 0, 0);
|
||||||
|
|
||||||
|
trace("thread: call PostMessage\n");
|
||||||
|
PostMessageA(wnd_event->hwnd, WM_USER+1, 0, 0);
|
||||||
|
|
||||||
|
/* this leads to sending an internal message under Wine */
|
||||||
|
trace("thread: call EnableWindow\n");
|
||||||
|
EnableWindow(wnd_event->hwnd, TRUE);
|
||||||
|
|
||||||
|
trace("thread: call SendMessage\n");
|
||||||
|
SendMessageA(wnd_event->hwnd, WM_USER+2, 0, 0);
|
||||||
|
|
||||||
|
trace("thread: call SendMessage\n");
|
||||||
|
SendMessageA(wnd_event->hwnd, WM_USER+3, 0, 0);
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void test_SendMessage_other_thread(int thread_n)
|
||||||
|
{
|
||||||
|
DWORD qs_all_input = QS_ALLINPUT & ~QS_RAWINPUT;
|
||||||
|
HANDLE hthread;
|
||||||
|
struct wnd_event wnd_event;
|
||||||
|
DWORD tid, ret;
|
||||||
|
MSG msg;
|
||||||
|
|
||||||
|
wnd_event.start_event = CreateEventA(NULL, 0, 0, NULL);
|
||||||
|
|
||||||
|
wnd_event.hwnd = CreateWindowExA(0, "TestWindowClass", NULL, WS_OVERLAPPEDWINDOW,
|
||||||
|
100, 100, 200, 200, 0, 0, 0, NULL);
|
||||||
|
ok(wnd_event.hwnd != 0, "CreateWindowEx failed\n");
|
||||||
|
|
||||||
|
hthread = CreateThread(NULL, 0, thread_n == 1 ? SendMessage_thread_1 : SendMessage_thread_2, &wnd_event, 0, &tid);
|
||||||
|
ok(hthread != NULL, "CreateThread failed, error %d\n", GetLastError());
|
||||||
|
CloseHandle(hthread);
|
||||||
|
|
||||||
|
flush_events();
|
||||||
|
flush_sequence();
|
||||||
|
|
||||||
|
ret = GetQueueStatus(QS_SENDMESSAGE);
|
||||||
|
ok(ret == 0, "wrong status %08x\n", ret);
|
||||||
|
|
||||||
|
SetEvent(wnd_event.start_event);
|
||||||
|
|
||||||
|
/* wait for other thread's SendMessage */
|
||||||
|
for (;;)
|
||||||
|
{
|
||||||
|
ret = GetQueueStatus(QS_SENDMESSAGE);
|
||||||
|
if (ret == MAKELONG(QS_SENDMESSAGE, QS_SENDMESSAGE)) break;
|
||||||
|
Sleep(50);
|
||||||
|
}
|
||||||
|
|
||||||
|
ret = GetQueueStatus(QS_SENDMESSAGE|QS_POSTMESSAGE);
|
||||||
|
todo_wine
|
||||||
|
ok(ret == MAKELONG(QS_POSTMESSAGE, QS_SENDMESSAGE|QS_POSTMESSAGE), "wrong status %08x\n", ret);
|
||||||
|
|
||||||
|
trace("main: call GetMessage\n");
|
||||||
|
GetMessageA(&msg, 0, 0, 0);
|
||||||
|
ok(msg.message == WM_USER, "expected WM_USER, got %04x\n", msg.message);
|
||||||
|
DispatchMessageA(&msg);
|
||||||
|
ok_sequence(send_message_1, "SendMessage from other thread 1", thread_n == 2);
|
||||||
|
|
||||||
|
/* intentionally yield */
|
||||||
|
MsgWaitForMultipleObjects(0, NULL, FALSE, 100, qs_all_input);
|
||||||
|
|
||||||
|
trace("main: call SendMessage\n");
|
||||||
|
SendMessageA(wnd_event.hwnd, WM_USER+4, 0, 0);
|
||||||
|
ok_sequence(send_message_2, "SendMessage from other thread 2", FALSE);
|
||||||
|
|
||||||
|
ret = GetQueueStatus(QS_SENDMESSAGE|QS_POSTMESSAGE);
|
||||||
|
ok(ret == MAKELONG(QS_SENDMESSAGE, QS_SENDMESSAGE|QS_POSTMESSAGE), "wrong status %08x\n", ret);
|
||||||
|
|
||||||
|
trace("main: call PeekMessage\n");
|
||||||
|
ok(PeekMessageA(&msg, 0, 0, 0, PM_REMOVE), "PeekMessage should not fail\n");
|
||||||
|
ok(msg.message == WM_USER+1, "expected WM_USER+1, got %04x\n", msg.message);
|
||||||
|
DispatchMessageA(&msg);
|
||||||
|
ok_sequence(send_message_3, "SendMessage from other thread 3", thread_n == 2);
|
||||||
|
|
||||||
|
/* intentionally yield */
|
||||||
|
MsgWaitForMultipleObjects(0, NULL, FALSE, 100, qs_all_input);
|
||||||
|
|
||||||
|
ret = GetQueueStatus(QS_SENDMESSAGE|QS_POSTMESSAGE);
|
||||||
|
/* FIXME: remove once Wine is fixed */
|
||||||
|
if (thread_n == 2) todo_wine
|
||||||
|
ok(ret == 0, "wrong status %08x\n", ret);
|
||||||
|
else
|
||||||
|
ok(ret == 0, "wrong status %08x\n", ret);
|
||||||
|
|
||||||
|
trace("main: call PeekMessage\n");
|
||||||
|
ok(!PeekMessageA(&msg, 0, 0, 0, PM_REMOVE), "PeekMessage should fail\n");
|
||||||
|
ok_sequence(WmEmptySeq, "SendMessage from other thread 4", thread_n == 2);
|
||||||
|
|
||||||
|
ret = GetQueueStatus(QS_SENDMESSAGE|QS_POSTMESSAGE);
|
||||||
|
ok(ret == 0, "wrong status %08x\n", ret);
|
||||||
|
|
||||||
|
trace("main: call DestroyWindow\n");
|
||||||
|
DestroyWindow(msg.hwnd);
|
||||||
|
|
||||||
|
flush_events();
|
||||||
|
flush_sequence();
|
||||||
|
}
|
||||||
|
|
||||||
static void init_funcs(void)
|
static void init_funcs(void)
|
||||||
{
|
{
|
||||||
HMODULE hKernel32 = GetModuleHandleA("kernel32.dll");
|
HMODULE hKernel32 = GetModuleHandleA("kernel32.dll");
|
||||||
|
@ -14675,6 +14822,9 @@ START_TEST(msg)
|
||||||
pUnhookWinEvent = 0;
|
pUnhookWinEvent = 0;
|
||||||
}
|
}
|
||||||
hEvent_hook = 0;
|
hEvent_hook = 0;
|
||||||
|
|
||||||
|
test_SendMessage_other_thread(1);
|
||||||
|
test_SendMessage_other_thread(2);
|
||||||
test_SetFocus();
|
test_SetFocus();
|
||||||
test_SetParent();
|
test_SetParent();
|
||||||
test_PostMessage();
|
test_PostMessage();
|
||||||
|
|
Loading…
Reference in New Issue