Arkadiusz Hiler : ucrtbase: Add tests for _beginthread[ex]().

Alexandre Julliard julliard at winehq.org
Wed May 5 16:09:01 CDT 2021


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

Author: Arkadiusz Hiler <ahiler at codeweavers.com>
Date:   Wed May  5 13:03:13 2021 +0300

ucrtbase: Add tests for _beginthread[ex]().

Signed-off-by: Arkadiusz Hiler <ahiler at codeweavers.com>
Signed-off-by: Piotr Caban <piotr at codeweavers.com>
Signed-off-by: Alexandre Julliard <julliard at winehq.org>

---

 dlls/ucrtbase/tests/Makefile.in    |   7 +-
 dlls/ucrtbase/tests/thread.c       | 147 +++++++++++++++++++++++++++++++++++++
 dlls/ucrtbase/tests/threaddll.c    |  67 +++++++++++++++++
 dlls/ucrtbase/tests/threaddll.h    |  30 ++++++++
 dlls/ucrtbase/tests/threaddll.spec |   3 +
 5 files changed, 252 insertions(+), 2 deletions(-)

diff --git a/dlls/ucrtbase/tests/Makefile.in b/dlls/ucrtbase/tests/Makefile.in
index 259880a7d90..4df5684290c 100644
--- a/dlls/ucrtbase/tests/Makefile.in
+++ b/dlls/ucrtbase/tests/Makefile.in
@@ -2,9 +2,12 @@ TESTDLL   = ucrtbase.dll
 IMPORTS   = ucrtbase
 EXTRADEFS = -fno-builtin
 
-C_SRCS = \
+SOURCES = \
 	cpp.c \
 	misc.c \
 	printf.c \
 	scanf.c \
-	string.c
+	string.c \
+	thread.c \
+	threaddll.c \
+	threaddll.spec
diff --git a/dlls/ucrtbase/tests/thread.c b/dlls/ucrtbase/tests/thread.c
new file mode 100644
index 00000000000..01f46029c06
--- /dev/null
+++ b/dlls/ucrtbase/tests/thread.c
@@ -0,0 +1,147 @@
+/*
+ * Copyright 2021 Arkadiusz Hiler for CodeWeavers
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
+ */
+
+#include <errno.h>
+#include <stdarg.h>
+#include <process.h>
+
+#include <windef.h>
+#include <winbase.h>
+#include "wine/test.h"
+
+#include "threaddll.h"
+
+enum beginthread_method
+{
+    use_beginthread,
+    use_beginthreadex
+};
+
+static char *get_thread_dll_path(void)
+{
+    static char path[MAX_PATH];
+    const char dll_name[] = "threaddll.dll";
+    DWORD written;
+    HANDLE file;
+    HRSRC res;
+    void *ptr;
+
+    GetTempPathA(ARRAY_SIZE(path), path);
+    strcat(path, dll_name);
+
+    file = CreateFileA(path, GENERIC_READ|GENERIC_WRITE, 0, NULL, CREATE_ALWAYS, 0, 0);
+    ok(file != INVALID_HANDLE_VALUE, "Failed to create file %s: %u.\n",
+            debugstr_a(path), GetLastError());
+
+    res = FindResourceA(NULL, dll_name, "TESTDLL");
+    ok(!!res, "Failed to load resource: %u\n", GetLastError());
+    ptr = LockResource(LoadResource(GetModuleHandleA(NULL), res));
+    WriteFile(file, ptr, SizeofResource( GetModuleHandleA(NULL), res), &written, NULL);
+    ok(written == SizeofResource(GetModuleHandleA(NULL), res), "Failed to write resource\n");
+    CloseHandle(file);
+
+    return path;
+}
+
+static void set_thead_dll_detach_event(HANDLE dll, HANDLE event)
+{
+    void WINAPI (*_set_detach_event)(HANDLE event);
+    _set_detach_event = (void*) GetProcAddress(dll, "set_detach_event");
+    ok(_set_detach_event != NULL, "Failed to get set_detach_event: %u\n", GetLastError());
+    _set_detach_event(event);
+}
+
+static void test_thread_library_reference(char *thread_dll,
+                                          enum beginthread_method beginthread_method,
+                                          enum thread_exit_method exit_method)
+{
+    HANDLE detach_event;
+    HMODULE dll;
+    DWORD ret;
+    uintptr_t thread_handle;
+    struct threaddll_args args;
+
+    args.exit_method = exit_method;
+
+    detach_event = CreateEventA(NULL, FALSE, FALSE, NULL);
+    ok(detach_event != NULL, "Failed to create an event: %u\n", GetLastError());
+    args.confirm_running = CreateEventA(NULL, FALSE, FALSE, NULL);
+    ok(args.confirm_running != NULL, "Failed to create an event: %u\n", GetLastError());
+    args.past_free = CreateEventA(NULL, FALSE, FALSE, NULL);
+    ok(args.past_free != NULL, "Failed to create an event: %u\n", GetLastError());
+
+    dll = LoadLibraryA(thread_dll);
+    ok(dll != NULL, "Failed to load the test dll: %u\n", GetLastError());
+
+    set_thead_dll_detach_event(dll, detach_event);
+
+    if (beginthread_method == use_beginthreadex)
+    {
+        _beginthreadex_start_routine_t proc = (void*) GetProcAddress(dll, "stdcall_thread_proc");
+        ok(proc != NULL, "Failed to get stdcall_thread_proc: %u\n", GetLastError());
+        thread_handle = _beginthreadex(NULL, 0, proc, &args, 0, NULL);
+    }
+    else
+    {
+        _beginthread_start_routine_t proc = (void*) GetProcAddress(dll, "cdecl_thread_proc");
+        ok(proc != NULL, "Failed to get stdcall_thread_proc: %u\n", GetLastError());
+        thread_handle = _beginthread(proc, 0, &args);
+    }
+
+    ok(thread_handle != -1 && thread_handle != 0, "Failed to begin thread: %u\n", errno);
+
+    ret = WaitForSingleObject(args.confirm_running, 200);
+    ok(ret == WAIT_OBJECT_0, "Event was not signaled, ret: %u, err: %u\n", ret, GetLastError());
+
+    ok(FreeLibrary(dll), "Failed to free the library: %u\n", GetLastError());
+
+    ret = WaitForSingleObject(detach_event, 0);
+    ok(ret == WAIT_TIMEOUT, "Thread detach happened unexpectedly signaling an event, ret: %d, err: %u\n", ret, GetLastError());
+
+    ok(SetEvent(args.past_free), "Failed to signal event: %d\n", GetLastError());
+
+    if (beginthread_method == use_beginthreadex)
+    {
+        ret = WaitForSingleObject((HANDLE)thread_handle, 200);
+        ok(ret == WAIT_OBJECT_0, "Thread has not exited, ret: %d, err: %u\n", ret, GetLastError());
+    }
+
+    ret = WaitForSingleObject(detach_event, 200);
+    ok(ret == WAIT_OBJECT_0, "Detach event was not signaled, ret: %d, err: %u\n", ret, GetLastError());
+
+    if (beginthread_method == use_beginthreadex)
+        CloseHandle((HANDLE)thread_handle);
+
+    CloseHandle(args.past_free);
+    CloseHandle(args.confirm_running);
+    CloseHandle(detach_event);
+}
+
+START_TEST(thread)
+{
+    BOOL ret;
+    char *thread_dll = get_thread_dll_path();
+
+    test_thread_library_reference(thread_dll, use_beginthread, thread_exit_return);
+    test_thread_library_reference(thread_dll, use_beginthread, thread_exit_endthread);
+    test_thread_library_reference(thread_dll, use_beginthreadex, thread_exit_return);
+    test_thread_library_reference(thread_dll, use_beginthreadex, thread_exit_endthreadex);
+
+    ret = DeleteFileA(thread_dll);
+    ok(ret, "Failed to remove the test dll, err: %u", GetLastError());
+}
diff --git a/dlls/ucrtbase/tests/threaddll.c b/dlls/ucrtbase/tests/threaddll.c
new file mode 100644
index 00000000000..72b8074054a
--- /dev/null
+++ b/dlls/ucrtbase/tests/threaddll.c
@@ -0,0 +1,67 @@
+/*
+ * Copyright 2021 Arkadiusz Hiler for CodeWeavers
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
+ */
+
+#include <windows.h>
+
+#include "threaddll.h"
+
+static HANDLE detach_event;
+
+void CDECL _endthread(void);
+void CDECL _endthreadex(unsigned int);
+
+void WINAPI set_detach_event(HANDLE event)
+{
+    detach_event = event;
+}
+
+static unsigned internal_thread_proc(void *param)
+{
+    struct threaddll_args *args = param;
+    SetEvent(args->confirm_running);
+    WaitForSingleObject(args->past_free, INFINITE);
+
+    if (args->exit_method == thread_exit_endthread)
+        _endthread();
+    else if (args->exit_method == thread_exit_endthreadex)
+        _endthreadex(0);
+
+    return 0;
+}
+
+unsigned WINAPI stdcall_thread_proc(void *param)
+{
+    return internal_thread_proc(param);
+}
+
+void CDECL cdecl_thread_proc(void *param)
+{
+    internal_thread_proc(param);
+}
+
+BOOL WINAPI DllMain(HINSTANCE instance_new, DWORD reason, LPVOID reserved)
+{
+    switch (reason)
+    {
+        case DLL_PROCESS_DETACH:
+            if (detach_event) SetEvent(detach_event);
+            break;
+    }
+
+    return TRUE;
+}
diff --git a/dlls/ucrtbase/tests/threaddll.h b/dlls/ucrtbase/tests/threaddll.h
new file mode 100644
index 00000000000..1d8d085798f
--- /dev/null
+++ b/dlls/ucrtbase/tests/threaddll.h
@@ -0,0 +1,30 @@
+/*
+ * Copyright 2021 Arkadiusz Hiler for CodeWeavers
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
+ */
+
+enum thread_exit_method {
+    thread_exit_return,
+    thread_exit_endthread,
+    thread_exit_endthreadex
+};
+
+struct threaddll_args
+{
+    HANDLE confirm_running;
+    HANDLE past_free;
+    enum thread_exit_method exit_method;
+};
diff --git a/dlls/ucrtbase/tests/threaddll.spec b/dlls/ucrtbase/tests/threaddll.spec
new file mode 100644
index 00000000000..8422c096946
--- /dev/null
+++ b/dlls/ucrtbase/tests/threaddll.spec
@@ -0,0 +1,3 @@
+@ stdcall set_detach_event(ptr)
+@ stdcall stdcall_thread_proc(ptr)
+@ cdecl cdecl_thread_proc(ptr)




More information about the wine-cvs mailing list