Alexandre Julliard : user32/tests: Add tests for message sequence of window destruction at thread exit.

Alexandre Julliard julliard at winehq.org
Wed Jun 3 09:31:14 CDT 2009


Module: wine
Branch: master
Commit: d25f71b55325941cc9c71a2da2604388e75041f9
URL:    http://source.winehq.org/git/wine.git/?a=commit;h=d25f71b55325941cc9c71a2da2604388e75041f9

Author: Alexandre Julliard <julliard at winehq.org>
Date:   Wed Jun  3 11:31:10 2009 +0200

user32/tests: Add tests for message sequence of window destruction at thread exit.

---

 dlls/user32/tests/msg.c |   80 ++++++++++++++++++++++++++++++++++++++++++++++-
 1 files changed, 79 insertions(+), 1 deletions(-)

diff --git a/dlls/user32/tests/msg.c b/dlls/user32/tests/msg.c
index 45ef814..72cf9ed 100644
--- a/dlls/user32/tests/msg.c
+++ b/dlls/user32/tests/msg.c
@@ -885,7 +885,7 @@ static const struct message WmShowVisiblePopupSeq_3[] = {
     { EVENT_OBJECT_FOCUS, winevent_hook|wparam|lparam, OBJID_CLIENT, 0 },
     { WM_SETFOCUS, sent|defwinproc },
     { WM_GETTEXT, sent|optional },
-    { WM_WINDOWPOSCHANGED, sent|wparam|optional, SWP_SHOWWINDOW|SWP_NOSIZE|SWP_NOMOVE|SWP_NOCLIENTSIZE|SWP_NOCLIENTMOVE },
+    { WM_WINDOWPOSCHANGED, sent|wparam|optional, SWP_NOSIZE|SWP_NOMOVE|SWP_NOCLIENTSIZE|SWP_NOCLIENTMOVE, 0, SWP_SHOWWINDOW },
     { 0 }
 };
 /* CreateWindow (for child window, not initially visible) */
@@ -1125,6 +1125,13 @@ static const struct message WmDestroyChildSeq[] = {
     { WM_NCDESTROY, sent },
     { 0 }
 };
+/* visible child window destroyed by thread exit */
+static const struct message WmExitThreadSeq[] = {
+    { WM_NCDESTROY, sent },  /* actually in grandchild */
+    { WM_PAINT, sent|parent },
+    { WM_ERASEBKGND, sent|parent|beginpaint },
+    { 0 }
+};
 /* DestroyWindow for a visible child window with invisible parent */
 static const struct message WmDestroyInvisibleChildSeq[] = {
     { HCBT_DESTROYWND, hook },
@@ -6334,6 +6341,53 @@ static DWORD WINAPI thread_proc(void *param)
     return 0;
 }
 
+static DWORD CALLBACK create_grand_child_thread( void *param )
+{
+    struct wnd_event *wnd_event = param;
+    HWND hchild;
+    MSG msg;
+
+    hchild = CreateWindowExA(0, "TestWindowClass", "Test child",
+                             WS_CHILD | WS_VISIBLE, 0, 0, 10, 10, wnd_event->hwnd, 0, 0, NULL);
+    ok (hchild != 0, "Failed to create child window\n");
+    flush_events();
+    flush_sequence();
+    SetEvent( wnd_event->event );
+
+    while (GetMessage(&msg, 0, 0, 0))
+    {
+	TranslateMessage(&msg);
+	DispatchMessage(&msg);
+        if (!IsWindow( hchild )) break;  /* will be destroyed when parent thread exits */
+    }
+    return 0;
+}
+
+static DWORD CALLBACK create_child_thread( void *param )
+{
+    struct wnd_event *wnd_event = param;
+    struct wnd_event child_event;
+    DWORD tid;
+    MSG msg;
+
+    child_event.hwnd = CreateWindowExA(0, "TestWindowClass", "Test child",
+                             WS_CHILD | WS_VISIBLE, 0, 0, 10, 10, wnd_event->hwnd, 0, 0, NULL);
+    ok (child_event.hwnd != 0, "Failed to create child window\n");
+    SetFocus( child_event.hwnd );
+    flush_events();
+    flush_sequence();
+    child_event.event = wnd_event->event;
+    CloseHandle( CreateThread(NULL, 0, create_grand_child_thread, &child_event, 0, &tid) );
+    for (;;)
+    {
+        DWORD ret = MsgWaitForMultipleObjects(1, &child_event.event, FALSE, 1000, QS_SENDMESSAGE);
+        if (ret != 1) break;
+        while (PeekMessageA(&msg, 0, 0, 0, PM_REMOVE)) DispatchMessage(&msg);
+    }
+    Sleep( 200 );  /* leave parent the time to finish processing messages */
+    return 0;
+}
+
 static void test_interthread_messages(void)
 {
     HANDLE hThread;
@@ -6401,6 +6455,30 @@ static void test_interthread_messages(void)
     CloseHandle(hThread);
 
     ok(!IsWindow(wnd_event.hwnd), "window should be destroyed on thread exit\n");
+
+    wnd_event.hwnd = CreateWindowExA(0, "TestParentClass", "Test parent", WS_OVERLAPPEDWINDOW | WS_VISIBLE,
+                              100, 100, 200, 200, 0, 0, 0, NULL);
+    ok (wnd_event.hwnd != 0, "Failed to create parent window\n");
+    flush_sequence();
+    log_all_parent_messages++;
+    wnd_event.event = CreateEventA( NULL, TRUE, FALSE, NULL );
+    hThread = CreateThread( NULL, 0, create_child_thread, &wnd_event, 0, &tid );
+    for (;;)
+    {
+        ret = MsgWaitForMultipleObjects(1, &wnd_event.event, FALSE, 1000, QS_SENDMESSAGE);
+        if (ret != 1) break;
+        while (PeekMessageA(&msg, 0, 0, 0, PM_REMOVE)) DispatchMessage(&msg);
+    }
+    ok( !ret, "MsgWaitForMultipleObjects failed %x\n", ret );
+    /* now wait for the thread without processing messages; this shouldn't deadlock */
+    ret = WaitForSingleObject( hThread, 5000 );
+    ok( !ret, "WaitForSingleObject failed %x\n", ret );
+    CloseHandle( hThread );
+    CloseHandle( wnd_event.event );
+    flush_events();
+    ok_sequence(WmExitThreadSeq, "destroy child on thread exit", FALSE);
+    log_all_parent_messages--;
+    DestroyWindow( wnd_event.hwnd );
 }
 
 




More information about the wine-cvs mailing list