So that we can have full featured wine test with thread local data and
context.
Signed-off-by: Rémi Bernon <rbernon(a)codeweavers.com>
---
Supersedes: 208930
v2: Same thing as before, but don't comment-out the okfile cleanup.
dlls/ntoskrnl.exe/tests/Makefile.in | 16 +-
dlls/ntoskrnl.exe/tests/driver.c | 36 ++--
dlls/ntoskrnl.exe/tests/driver.h | 8 -
dlls/ntoskrnl.exe/tests/driver_hid.c | 2 +-
dlls/ntoskrnl.exe/tests/driver_netio.c | 6 +-
dlls/ntoskrnl.exe/tests/driver_pnp.c | 2 +-
dlls/ntoskrnl.exe/tests/ntoskrnl.c | 49 +----
dlls/ntoskrnl.exe/tests/utils.h | 257 ------------------------
include/wine/test.h | 260 +++++++++++++++++++++++--
9 files changed, 287 insertions(+), 349 deletions(-)
delete mode 100644 dlls/ntoskrnl.exe/tests/utils.h
diff --git a/dlls/ntoskrnl.exe/tests/Makefile.in b/dlls/ntoskrnl.exe/tests/Makefile.in
index 863fad30f63..037f0fda637 100644
--- a/dlls/ntoskrnl.exe/tests/Makefile.in
+++ b/dlls/ntoskrnl.exe/tests/Makefile.in
@@ -1,17 +1,23 @@
TESTDLL = ntoskrnl.exe
IMPORTS = advapi32 crypt32 newdev setupapi user32 wintrust ws2_32 hid
-driver_IMPORTS = winecrt0 ntoskrnl
+driver_IMPORTS = winecrt0 ntoskrnl hal
+driver_EXTRADEFS = -DSTANDALONE -DWINETEST_KERNEL
driver_EXTRADLLFLAGS = -nodefaultlibs -nostartfiles -Wl,--subsystem,native
-driver2_IMPORTS = winecrt0 ntoskrnl
+driver2_IMPORTS = winecrt0 ntoskrnl hal
+driver2_EXTRADEFS = -DSTANDALONE -DWINETEST_KERNEL
driver2_EXTRADLLFLAGS = -nodefaultlibs -nostartfiles -Wl,--subsystem,native
-driver3_IMPORTS = winecrt0 ntoskrnl
+driver3_IMPORTS = winecrt0 ntoskrnl hal
+driver3_EXTRADEFS = -DSTANDALONE -DWINETEST_KERNEL
driver3_EXTRADLLFLAGS = -nodefaultlibs -nostartfiles -Wl,--subsystem,native
-driver_hid_IMPORTS = winecrt0 ntoskrnl hidclass
+driver_hid_IMPORTS = winecrt0 ntoskrnl hal hidclass
+driver_hid_EXTRADEFS = -DSTANDALONE -DWINETEST_KERNEL
driver_hid_EXTRADLLFLAGS = -nodefaultlibs -nostartfiles -Wl,--subsystem,native
-driver_netio_IMPORTS = winecrt0 ntoskrnl netio
+driver_netio_IMPORTS = winecrt0 ntoskrnl hal netio
+driver_netio_EXTRADEFS = -DSTANDALONE -DWINETEST_KERNEL
driver_netio_EXTRADLLFLAGS = -nodefaultlibs -nostartfiles -Wl,--subsystem,native
driver_pnp_IMPORTS = winecrt0 ntoskrnl hal
+driver_pnp_EXTRADEFS = -DSTANDALONE -DWINETEST_KERNEL
driver_pnp_EXTRADLLFLAGS = -nodefaultlibs -nostartfiles -Wl,--subsystem,native
SOURCES = \
diff --git a/dlls/ntoskrnl.exe/tests/driver.c b/dlls/ntoskrnl.exe/tests/driver.c
index 94139b4b654..8c5ac6d89d4 100644
--- a/dlls/ntoskrnl.exe/tests/driver.c
+++ b/dlls/ntoskrnl.exe/tests/driver.c
@@ -33,9 +33,9 @@
#include "ddk/ntifs.h"
#include "ddk/wdm.h"
-#include "driver.h"
+#include "wine/test.h"
-#include "utils.h"
+#include "driver.h"
/* memcmp() isn't exported from ntoskrnl on i386 */
static int kmemcmp( const void *ptr1, const void *ptr2, size_t n )
@@ -999,41 +999,41 @@ static void test_call_driver(DEVICE_OBJECT *device)
irp = IoBuildAsynchronousFsdRequest(IRP_MJ_FLUSH_BUFFERS, device, NULL, 0, NULL, &iosb);
ok(irp->UserIosb == &iosb, "unexpected UserIosb\n");
ok(!irp->Cancel, "Cancel = %x\n", irp->Cancel);
- ok(!irp->CancelRoutine, "CancelRoutine = %x\n", irp->CancelRoutine);
+ ok(!irp->CancelRoutine, "CancelRoutine = %p\n", irp->CancelRoutine);
ok(!irp->UserEvent, "UserEvent = %p\n", irp->UserEvent);
ok(irp->CurrentLocation == 2, "CurrentLocation = %u\n", irp->CurrentLocation);
ok(irp->Tail.Overlay.Thread == (PETHREAD)KeGetCurrentThread(),
"IRP thread is not the current thread\n");
ok(!irp->IoStatus.Status, "got status %#x\n", irp->IoStatus.Status);
- ok(!irp->IoStatus.Information, "got information %#x\n", irp->IoStatus.Information);
+ ok(!irp->IoStatus.Information, "got information %#I64x\n", (UINT64)irp->IoStatus.Information);
ok(iosb.Status == 0xdeadbeef, "got status %#x\n", iosb.Status);
- ok(iosb.Information == 0xdeadbeef, "got information %#x\n", iosb.Information);
+ ok(iosb.Information == 0xdeadbeef, "got information %#I64x\n", (UINT64)iosb.Information);
irpsp = IoGetNextIrpStackLocation(irp);
ok(irpsp->MajorFunction == IRP_MJ_FLUSH_BUFFERS, "MajorFunction = %u\n", irpsp->MajorFunction);
- ok(!irpsp->DeviceObject, "DeviceObject = %u\n", irpsp->DeviceObject);
- ok(!irpsp->FileObject, "FileObject = %u\n", irpsp->FileObject);
+ ok(!irpsp->DeviceObject, "DeviceObject = %p\n", irpsp->DeviceObject);
+ ok(!irpsp->FileObject, "FileObject = %p\n", irpsp->FileObject);
ok(!irpsp->CompletionRoutine, "CompletionRoutine = %p\n", irpsp->CompletionRoutine);
status = IoCallDriver(device, irp);
ok(status == STATUS_PENDING, "IoCallDriver returned %#x\n", status);
ok(!irp->IoStatus.Status, "got status %#x\n", irp->IoStatus.Status);
- ok(!irp->IoStatus.Information, "got information %#x\n", irp->IoStatus.Information);
+ ok(!irp->IoStatus.Information, "got information %#I64x\n", (UINT64)irp->IoStatus.Information);
ok(iosb.Status == 0xdeadbeef, "got status %#x\n", iosb.Status);
- ok(iosb.Information == 0xdeadbeef, "got information %#x\n", iosb.Information);
+ ok(iosb.Information == 0xdeadbeef, "got information %#I64x\n", (UINT64)iosb.Information);
irp->IoStatus.Status = STATUS_SUCCESS;
irp->IoStatus.Information = 123;
IoCompleteRequest(irp, IO_NO_INCREMENT);
ok(iosb.Status == STATUS_SUCCESS, "got status %#x\n", iosb.Status);
- ok(iosb.Information == 123, "got information %#x\n", iosb.Information);
+ ok(iosb.Information == 123, "got information %#I64x\n", (UINT64)iosb.Information);
KeInitializeEvent(&event, NotificationEvent, FALSE);
irp = IoBuildSynchronousFsdRequest(IRP_MJ_FLUSH_BUFFERS, device, NULL, 0, NULL, &event, &iosb);
ok(irp->UserIosb == &iosb, "unexpected UserIosb\n");
ok(!irp->Cancel, "Cancel = %x\n", irp->Cancel);
- ok(!irp->CancelRoutine, "CancelRoutine = %x\n", irp->CancelRoutine);
+ ok(!irp->CancelRoutine, "CancelRoutine = %p\n", irp->CancelRoutine);
ok(irp->UserEvent == &event, "UserEvent = %p\n", irp->UserEvent);
ok(irp->CurrentLocation == 2, "CurrentLocation = %u\n", irp->CurrentLocation);
ok(irp->Tail.Overlay.Thread == (PETHREAD)KeGetCurrentThread(),
@@ -1041,8 +1041,8 @@ static void test_call_driver(DEVICE_OBJECT *device)
irpsp = IoGetNextIrpStackLocation(irp);
ok(irpsp->MajorFunction == IRP_MJ_FLUSH_BUFFERS, "MajorFunction = %u\n", irpsp->MajorFunction);
- ok(!irpsp->DeviceObject, "DeviceObject = %u\n", irpsp->DeviceObject);
- ok(!irpsp->FileObject, "FileObject = %u\n", irpsp->FileObject);
+ ok(!irpsp->DeviceObject, "DeviceObject = %p\n", irpsp->DeviceObject);
+ ok(!irpsp->FileObject, "FileObject = %p\n", irpsp->FileObject);
ok(!irpsp->CompletionRoutine, "CompletionRoutine = %p\n", irpsp->CompletionRoutine);
status = wait_single(&event, 0);
@@ -1118,7 +1118,7 @@ static void test_cancel_irp(DEVICE_OBJECT *device)
ok(irp->CurrentLocation == 1, "CurrentLocation = %u\n", irp->CurrentLocation);
irpsp = IoGetCurrentIrpStackLocation(irp);
- ok(irpsp->DeviceObject == device, "DeviceObject = %u\n", irpsp->DeviceObject);
+ ok(irpsp->DeviceObject == device, "DeviceObject = %p\n", irpsp->DeviceObject);
IoSetCancelRoutine(irp, cancel_irp);
cancel_cnt = 0;
@@ -1432,16 +1432,16 @@ static void check_resource_(int line, ERESOURCE *resource, ULONG exclusive_waite
ULONG count;
count = ExGetExclusiveWaiterCount(resource);
- ok_(__FILE__, line, count == exclusive_waiters,
+ ok_(__FILE__, line)(count == exclusive_waiters,
"expected %u exclusive waiters, got %u\n", exclusive_waiters, count);
count = ExGetSharedWaiterCount(resource);
- ok_(__FILE__, line, count == shared_waiters,
+ ok_(__FILE__, line)(count == shared_waiters,
"expected %u shared waiters, got %u\n", shared_waiters, count);
ret = ExIsResourceAcquiredExclusiveLite(resource);
- ok_(__FILE__, line, ret == exclusive,
+ ok_(__FILE__, line)(ret == exclusive,
"expected exclusive %u, got %u\n", exclusive, ret);
count = ExIsResourceAcquiredSharedLite(resource);
- ok_(__FILE__, line, count == shared_count,
+ ok_(__FILE__, line)(count == shared_count,
"expected shared %u, got %u\n", shared_count, count);
}
#define check_resource(a,b,c,d,e) check_resource_(__LINE__,a,b,c,d,e)
diff --git a/dlls/ntoskrnl.exe/tests/driver.h b/dlls/ntoskrnl.exe/tests/driver.h
index 455695ad36b..01d0991a25c 100644
--- a/dlls/ntoskrnl.exe/tests/driver.h
+++ b/dlls/ntoskrnl.exe/tests/driver.h
@@ -49,14 +49,6 @@
static const char teststr[] = "Wine is not an emulator";
-struct test_data
-{
- int running_under_wine;
- int winetest_report_success;
- int winetest_debug;
- int successes, failures, skipped, todo_successes, todo_failures;
-};
-
struct main_test_input
{
DWORD process_id;
diff --git a/dlls/ntoskrnl.exe/tests/driver_hid.c b/dlls/ntoskrnl.exe/tests/driver_hid.c
index 793b25f3189..ed3e5c17d6f 100644
--- a/dlls/ntoskrnl.exe/tests/driver_hid.c
+++ b/dlls/ntoskrnl.exe/tests/driver_hid.c
@@ -32,10 +32,10 @@
#include "ddk/hidpi.h"
#include "ddk/hidport.h"
+#include "wine/test.h"
#include "wine/list.h"
#include "driver.h"
-#include "utils.h"
static UNICODE_STRING control_symlink;
diff --git a/dlls/ntoskrnl.exe/tests/driver_netio.c b/dlls/ntoskrnl.exe/tests/driver_netio.c
index ea9cfd1a4c5..68dbfd1c5e8 100644
--- a/dlls/ntoskrnl.exe/tests/driver_netio.c
+++ b/dlls/ntoskrnl.exe/tests/driver_netio.c
@@ -32,9 +32,9 @@
#include "ddk/wdm.h"
#include "ddk/wsk.h"
-#include "driver.h"
+#include "wine/test.h"
-#include "utils.h"
+#include "driver.h"
static DRIVER_OBJECT *driver_obj;
static DEVICE_OBJECT *device_obj;
@@ -141,7 +141,7 @@ static void test_wsk_get_address_info(void)
{
struct sockaddr_in *addr = (struct sockaddr_in *)addr_info->ai_addr;
- ok(addr_info->ai_addrlen == sizeof(*addr), "Got unexpected ai_addrlen %u.\n", addr_info->ai_addrlen);
+ ok(addr_info->ai_addrlen == sizeof(*addr), "Got unexpected ai_addrlen %I64u.\n", (UINT64)addr_info->ai_addrlen);
ok(addr->sin_family == AF_INET, "Got unexpected sin_family %u.\n", addr->sin_family);
ok(ntohs(addr->sin_port) == 12345, "Got unexpected sin_port %u.\n", ntohs(addr->sin_port));
ok(ntohl(addr->sin_addr.s_addr) == 0x7f000001, "Got unexpected sin_addr %#x.\n",
diff --git a/dlls/ntoskrnl.exe/tests/driver_pnp.c b/dlls/ntoskrnl.exe/tests/driver_pnp.c
index 98ca2ff7961..cf672f6f397 100644
--- a/dlls/ntoskrnl.exe/tests/driver_pnp.c
+++ b/dlls/ntoskrnl.exe/tests/driver_pnp.c
@@ -29,10 +29,10 @@
#include "winioctl.h"
#include "ddk/wdm.h"
+#include "wine/test.h"
#include "wine/list.h"
#include "driver.h"
-#include "utils.h"
static const GUID bus_class = {0xdeadbeef, 0x29ef, 0x4538, {0xa5, 0xfd, 0xb6, 0x95, 0x73, 0xa3, 0x62, 0xc1}};
static const GUID child_class = {0xdeadbeef, 0x29ef, 0x4538, {0xa5, 0xfd, 0xb6, 0x95, 0x73, 0xa3, 0x62, 0xc2}};
diff --git a/dlls/ntoskrnl.exe/tests/ntoskrnl.c b/dlls/ntoskrnl.exe/tests/ntoskrnl.c
index 0ef621011d3..c3456e56274 100644
--- a/dlls/ntoskrnl.exe/tests/ntoskrnl.c
+++ b/dlls/ntoskrnl.exe/tests/ntoskrnl.c
@@ -52,8 +52,6 @@ static const GUID GUID_NULL;
static HANDLE device;
-static struct test_data *test_data;
-
static BOOL (WINAPI *pRtlDosPathNameToNtPathName_U)(const WCHAR *, UNICODE_STRING *, WCHAR **, CURDIR *);
static BOOL (WINAPI *pRtlFreeUnicodeString)(UNICODE_STRING *);
static BOOL (WINAPI *pCancelIoEx)(HANDLE, OVERLAPPED *);
@@ -367,27 +365,6 @@ static BOOL start_driver(HANDLE service, BOOL vista_plus)
return TRUE;
}
-static HANDLE okfile;
-
-static void cat_okfile(void)
-{
- char buffer[512];
- DWORD size;
-
- SetFilePointer(okfile, 0, NULL, FILE_BEGIN);
-
- do
- {
- ReadFile(okfile, buffer, sizeof(buffer), &size, NULL);
- printf("%.*s", size, buffer);
- } while (size == sizeof(buffer));
-
- SetFilePointer(okfile, 0, NULL, FILE_BEGIN);
- SetEndOfFile(okfile);
-
- winetest_add_failures(InterlockedExchange(&test_data->failures, 0));
-}
-
static ULONG64 modified_value;
static void main_test(void)
@@ -931,7 +908,7 @@ static void test_driver_netio(struct testsign_context *ctx)
ret = DeleteFileW(filename);
ok(ret, "DeleteFile failed: %u\n", GetLastError());
- cat_okfile();
+ winetest_kernel_check();
}
#ifdef __i386__
@@ -1499,7 +1476,7 @@ static void test_pnp_driver(struct testsign_context *ctx)
unload_driver(service);
CloseServiceHandle(manager);
- cat_okfile();
+ winetest_kernel_check();
GetFullPathNameA("winetest.inf", sizeof(path), path, NULL);
ret = SetupCopyOEMInfA(path, NULL, 0, 0, dest, sizeof(dest), NULL, &filepart);
@@ -2638,7 +2615,7 @@ static void test_hid_driver(struct testsign_context *ctx, DWORD report_id)
unload_driver(service);
CloseServiceHandle(manager);
- cat_okfile();
+ winetest_kernel_check();
GetFullPathNameA("winetest.inf", sizeof(path), path, NULL);
ret = SetupCopyOEMInfA(path, NULL, 0, 0, dest, sizeof(dest), NULL, &filepart);
@@ -2665,7 +2642,6 @@ START_TEST(ntoskrnl)
struct testsign_context ctx;
SC_HANDLE service, service2;
BOOL ret, is_wow64;
- HANDLE mapping;
DWORD written;
pRtlDosPathNameToNtPathName_U = (void *)GetProcAddress(GetModuleHandleA("ntdll"), "RtlDosPathNameToNtPathName_U");
@@ -2685,17 +2661,7 @@ START_TEST(ntoskrnl)
if (!testsign_create_cert(&ctx))
return;
- mapping = CreateFileMappingA(INVALID_HANDLE_VALUE, NULL, PAGE_READWRITE,
- 0, sizeof(*test_data), "Global\\winetest_ntoskrnl_section");
- ok(!!mapping, "got error %u\n", GetLastError());
- test_data = MapViewOfFile(mapping, FILE_MAP_READ | FILE_MAP_WRITE, 0, 0, 1024);
- test_data->running_under_wine = !strcmp(winetest_platform, "wine");
- test_data->winetest_report_success = winetest_report_success;
- test_data->winetest_debug = winetest_debug;
-
- okfile = CreateFileA("C:\\windows\\winetest_ntoskrnl_okfile", GENERIC_READ | GENERIC_WRITE,
- FILE_SHARE_READ | FILE_SHARE_WRITE, NULL, CREATE_ALWAYS, 0, NULL);
- ok(okfile != INVALID_HANDLE_VALUE, "failed to create file, error %u\n", GetLastError());
+ winetest_kernel_init();
subtest("driver");
if (!(service = load_driver(&ctx, filename, L"driver.dll", L"WineTestDriver")))
@@ -2737,7 +2703,7 @@ START_TEST(ntoskrnl)
ret = DeleteFileW(filename2);
ok(ret, "DeleteFile failed: %u\n", GetLastError());
- cat_okfile();
+ winetest_kernel_check();
test_driver3(&ctx);
subtest("driver_netio");
@@ -2752,8 +2718,5 @@ START_TEST(ntoskrnl)
out:
testsign_cleanup(&ctx);
- UnmapViewOfFile(test_data);
- CloseHandle(mapping);
- CloseHandle(okfile);
- DeleteFileA("C:\\windows\\winetest_ntoskrnl_okfile");
+ winetest_kernel_cleanup();
}
diff --git a/dlls/ntoskrnl.exe/tests/utils.h b/dlls/ntoskrnl.exe/tests/utils.h
deleted file mode 100644
index 6a0e00428a5..00000000000
--- a/dlls/ntoskrnl.exe/tests/utils.h
+++ /dev/null
@@ -1,257 +0,0 @@
-/*
- * ntoskrnl.exe testing framework
- *
- * Copyright 2015 Sebastian Lackner
- * Copyright 2015 Michael Müller
- * Copyright 2015 Christian Costa
- * Copyright 2020 Paul Gofman for CodeWeavers
- * Copyright 2020-2021 Zebediah Figura 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
- */
-
-static HANDLE okfile;
-static LONG successes;
-static LONG failures;
-static LONG skipped;
-static LONG todo_successes;
-static LONG todo_failures;
-static int todo_level, todo_do_loop;
-static int running_under_wine;
-static int winetest_debug;
-static int winetest_report_success;
-
-static inline void kvprintf(const char *format, __ms_va_list ap)
-{
- static char buffer[512];
- IO_STATUS_BLOCK io;
- int len = vsnprintf(buffer, sizeof(buffer), format, ap);
- ZwWriteFile(okfile, NULL, NULL, NULL, &io, buffer, len, NULL, NULL);
-}
-
-static inline void WINAPIV kprintf(const char *format, ...)
-{
- __ms_va_list valist;
-
- __ms_va_start(valist, format);
- kvprintf(format, valist);
- __ms_va_end(valist);
-}
-
-static inline NTSTATUS winetest_init(void)
-{
- const struct test_data *data;
- SIZE_T size = sizeof(*data);
- OBJECT_ATTRIBUTES attr;
- UNICODE_STRING string;
- IO_STATUS_BLOCK io;
- void *addr = NULL;
- HANDLE section;
- NTSTATUS ret;
-
- RtlInitUnicodeString(&string, L"\\BaseNamedObjects\\winetest_ntoskrnl_section");
- /* OBJ_KERNEL_HANDLE is necessary for the file to be accessible from system threads */
- InitializeObjectAttributes(&attr, &string, OBJ_CASE_INSENSITIVE | OBJ_KERNEL_HANDLE, 0, NULL);
- if ((ret = ZwOpenSection(§ion, SECTION_MAP_READ, &attr)))
- return ret;
-
- if ((ret = ZwMapViewOfSection(section, NtCurrentProcess(), &addr,
- 0, 0, NULL, &size, ViewUnmap, 0, PAGE_READONLY)))
- {
- ZwClose(section);
- return ret;
- }
- data = addr;
- running_under_wine = data->running_under_wine;
- winetest_debug = data->winetest_debug;
- winetest_report_success = data->winetest_report_success;
-
- ZwUnmapViewOfSection(NtCurrentProcess(), addr);
- ZwClose(section);
-
- RtlInitUnicodeString(&string, L"\\??\\C:\\windows\\winetest_ntoskrnl_okfile");
- return ZwOpenFile(&okfile, FILE_APPEND_DATA | SYNCHRONIZE, &attr, &io,
- FILE_SHARE_READ | FILE_SHARE_WRITE, FILE_SYNCHRONOUS_IO_NONALERT);
-}
-
-static inline void winetest_cleanup(void)
-{
- struct test_data *data;
- SIZE_T size = sizeof(*data);
- OBJECT_ATTRIBUTES attr;
- UNICODE_STRING string;
- void *addr = NULL;
- HANDLE section;
-
- if (winetest_debug)
- {
- kprintf("%04x:ntoskrnl: %d tests executed (%d marked as todo, %d %s), %d skipped.\n",
- PsGetCurrentProcessId(), successes + failures + todo_successes + todo_failures,
- todo_successes, failures + todo_failures,
- (failures + todo_failures != 1) ? "failures" : "failure", skipped );
- }
-
- RtlInitUnicodeString(&string, L"\\BaseNamedObjects\\winetest_ntoskrnl_section");
- /* OBJ_KERNEL_HANDLE is necessary for the file to be accessible from system threads */
- InitializeObjectAttributes(&attr, &string, OBJ_CASE_INSENSITIVE | OBJ_KERNEL_HANDLE, 0, NULL);
-
- if (!ZwOpenSection(§ion, SECTION_MAP_READ | SECTION_MAP_WRITE, &attr))
- {
- if (!ZwMapViewOfSection(section, NtCurrentProcess(), &addr,
- 0, 0, NULL, &size, ViewUnmap, 0, PAGE_READWRITE))
- {
- data = addr;
-
- InterlockedExchangeAdd(&data->successes, successes);
- InterlockedExchangeAdd(&data->failures, failures);
- InterlockedExchangeAdd(&data->skipped, skipped);
- InterlockedExchangeAdd(&data->todo_successes, todo_successes);
- InterlockedExchangeAdd(&data->todo_failures, todo_failures);
-
- ZwUnmapViewOfSection(NtCurrentProcess(), addr);
- }
- ZwClose(section);
- }
-
- ZwClose(okfile);
-}
-
-static inline void WINAPIV vok_(const char *file, int line, int condition, const char *msg, __ms_va_list args)
-{
- const char *current_file;
-
- if (!(current_file = drv_strrchr(file, '/')) &&
- !(current_file = drv_strrchr(file, '\\')))
- current_file = file;
- else
- current_file++;
-
- if (todo_level)
- {
- if (condition)
- {
- kprintf("%s:%d: Test succeeded inside todo block: ", current_file, line);
- kvprintf(msg, args);
- InterlockedIncrement(&todo_failures);
- }
- else
- {
- if (winetest_debug > 0)
- {
- kprintf("%s:%d: Test marked todo: ", current_file, line);
- kvprintf(msg, args);
- }
- InterlockedIncrement(&todo_successes);
- }
- }
- else
- {
- if (!condition)
- {
- kprintf("%s:%d: Test failed: ", current_file, line);
- kvprintf(msg, args);
- InterlockedIncrement(&failures);
- }
- else
- {
- if (winetest_report_success)
- kprintf("%s:%d: Test succeeded\n", current_file, line);
- InterlockedIncrement(&successes);
- }
- }
-}
-
-static inline void WINAPIV ok_(const char *file, int line, int condition, const char *msg, ...)
-{
- __ms_va_list args;
- __ms_va_start(args, msg);
- vok_(file, line, condition, msg, args);
- __ms_va_end(args);
-}
-
-static inline void vskip_(const char *file, int line, const char *msg, __ms_va_list args)
-{
- const char *current_file;
-
- if (!(current_file = drv_strrchr(file, '/')) &&
- !(current_file = drv_strrchr(file, '\\')))
- current_file = file;
- else
- current_file++;
-
- kprintf("%s:%d: Tests skipped: ", current_file, line);
- kvprintf(msg, args);
- skipped++;
-}
-
-static inline void WINAPIV win_skip_(const char *file, int line, const char *msg, ...)
-{
- __ms_va_list args;
- __ms_va_start(args, msg);
- if (running_under_wine)
- vok_(file, line, 0, msg, args);
- else
- vskip_(file, line, msg, args);
- __ms_va_end(args);
-}
-
-static inline void WINAPIV trace_(const char *file, int line, const char *msg, ...)
-{
- const char *current_file;
- __ms_va_list args;
-
- if (!(current_file = drv_strrchr(file, '/')) &&
- !(current_file = drv_strrchr(file, '\\')))
- current_file = file;
- else
- current_file++;
-
- __ms_va_start(args, msg);
- kprintf("%s:%d: ", current_file, line);
- kvprintf(msg, args);
- __ms_va_end(args);
-}
-
-static inline void winetest_start_todo( int is_todo )
-{
- todo_level = (todo_level << 1) | (is_todo != 0);
- todo_do_loop=1;
-}
-
-static inline int winetest_loop_todo(void)
-{
- int do_loop=todo_do_loop;
- todo_do_loop=0;
- return do_loop;
-}
-
-static inline void winetest_end_todo(void)
-{
- todo_level >>= 1;
-}
-
-static inline int broken(int condition)
-{
- return !running_under_wine && condition;
-}
-
-#define ok(condition, ...) ok_(__FILE__, __LINE__, condition, __VA_ARGS__)
-#define todo_if(is_todo) for (winetest_start_todo(is_todo); \
- winetest_loop_todo(); \
- winetest_end_todo())
-#define todo_wine todo_if(running_under_wine)
-#define todo_wine_if(is_todo) todo_if((is_todo) && running_under_wine)
-#define win_skip(...) win_skip_(__FILE__, __LINE__, __VA_ARGS__)
-#define trace(...) trace_(__FILE__, __LINE__, __VA_ARGS__)
diff --git a/include/wine/test.h b/include/wine/test.h
index 8073071d262..ede648fb717 100644
--- a/include/wine/test.h
+++ b/include/wine/test.h
@@ -25,6 +25,9 @@
#include <stdlib.h>
#include <windef.h>
#include <winbase.h>
+#ifdef WINETEST_KERNEL
+#include <ddk/wdm.h>
+#endif /* WINETEST_KERNEL */
#include <wine/debug.h>
#ifdef __WINE_CONFIG_H
@@ -59,6 +62,9 @@ extern int winetest_mute_threshold;
/* current platform */
extern const char *winetest_platform;
+/* output file for kernel tests */
+extern HANDLE okfile;
+
extern void winetest_set_location( const char* file, int line );
extern void winetest_subtest( const char* name );
extern void winetest_ignore_exceptions( BOOL ignore );
@@ -68,6 +74,9 @@ extern void winetest_end_todo(void);
extern int winetest_get_mainargs( char*** pargv );
extern LONG winetest_get_failures(void);
extern void winetest_add_failures( LONG new_failures );
+extern void winetest_kernel_init( void );
+extern void winetest_kernel_check( void );
+extern void winetest_kernel_cleanup( void );
extern void winetest_wait_child_process( HANDLE process );
#ifdef STANDALONE
@@ -214,7 +223,8 @@ DWORD winetest_start_time, winetest_last_time;
int winetest_interactive = 0;
/* current platform */
-const char *winetest_platform = "windows";
+static char winetest_platform_buf[256] = "windows";
+const char *winetest_platform = winetest_platform_buf;
/* report successful tests (BOOL) */
int winetest_report_success = 0;
@@ -226,7 +236,9 @@ int winetest_mute_threshold = 42;
static int winetest_argc;
static char** winetest_argv;
+#ifndef WINETEST_KERNEL
static const struct test *current_test; /* test currently being run */
+#endif /* WINETEST_KERNEL */
static LONG successes; /* number of successful tests */
static LONG failures; /* number of failures */
@@ -240,9 +252,15 @@ static LONG muted_todo_successes; /* same as todo_successes but silent */
/* counts how many times a given line printed a message */
static LONG line_counters[16384];
+/* output file for driver tests */
+HANDLE okfile;
+
/* The following data must be kept track of on a per-thread basis */
struct tls_data
{
+#ifdef WINETEST_KERNEL
+ HANDLE thread;
+#endif /* WINETEST_KERNEL */
const char* current_file; /* file of current check */
int current_line; /* line of current check */
unsigned int todo_level; /* current todo nesting level */
@@ -252,6 +270,38 @@ struct tls_data
char context[8][128]; /* data to print before messages */
unsigned int context_count; /* number of context prefixes */
};
+
+#ifdef WINETEST_KERNEL
+
+static KSPIN_LOCK tls_data_lock;
+static struct tls_data tls_data_pool[128];
+static DWORD tls_data_count;
+
+static struct tls_data *get_tls_data(void)
+{
+ static struct tls_data tls_overflow;
+ struct tls_data *data;
+ HANDLE thread = PsGetCurrentThreadId();
+ KIRQL irql;
+
+ KeAcquireSpinLock(&tls_data_lock, &irql);
+ for (data = tls_data_pool; data != tls_data_pool + tls_data_count; ++data)
+ if (data->thread == thread) break;
+ if (data == tls_data_pool + ARRAY_SIZE(tls_data_pool))
+ data = &tls_overflow;
+ else if (data == tls_data_pool + tls_data_count)
+ {
+ data->thread = thread;
+ data->str_pos = data->strings;
+ tls_data_count++;
+ }
+ KeReleaseSpinLock(&tls_data_lock, irql);
+
+ return data;
+}
+
+#else /* WINETEST_KERNEL */
+
static DWORD tls_index;
static struct tls_data *get_tls_data(void)
@@ -277,6 +327,7 @@ static void exit_process( int code )
ExitProcess( code );
}
+#endif /* WINETEST_KERNEL */
void winetest_set_location( const char* file, int line )
{
@@ -291,6 +342,36 @@ void winetest_set_location( const char* file, int line )
data->current_line=line;
}
+#ifdef WINETEST_KERNEL
+
+static inline void __winetest_vprintf(const char *format, __ms_va_list ap)
+{
+ static char buffer[512];
+ IO_STATUS_BLOCK io;
+ int len = vsnprintf(buffer, sizeof(buffer), format, ap);
+ ZwWriteFile(okfile, NULL, NULL, NULL, &io, buffer, len, NULL, NULL);
+}
+
+static inline void WINAPIV __winetest_printf(const char *format, ...)
+{
+ __ms_va_list valist;
+
+ __ms_va_start(valist, format);
+ __winetest_vprintf(format, valist);
+ __ms_va_end(valist);
+}
+
+const char *winetest_elapsed(void)
+{
+ if (!winetest_time) return "";
+ return "0.000";
+}
+
+#else /* WINETEST_KERNEL */
+
+#define __winetest_printf printf
+#define __winetest_vprintf vprintf
+
const char *winetest_elapsed(void)
{
DWORD now;
@@ -300,15 +381,17 @@ const char *winetest_elapsed(void)
return wine_dbg_sprintf( "%.3f", (now - winetest_start_time) / 1000.0);
}
+#endif /* WINETEST_KERNEL */
+
static void __winetest_cdecl winetest_printf( const char *msg, ... ) __WINE_PRINTF_ATTR(1,2);
static void __winetest_cdecl winetest_printf( const char *msg, ... )
{
struct tls_data *data = get_tls_data();
__winetest_va_list valist;
- printf( "%s:%d:%s ", data->current_file, data->current_line, winetest_elapsed() );
+ __winetest_printf( "%s:%d:%s ", data->current_file, data->current_line, winetest_elapsed() );
__winetest_va_start( valist, msg );
- vprintf( msg, valist );
+ __winetest_vprintf( msg, valist );
__winetest_va_end( valist );
}
static void __winetest_cdecl winetest_print_context( const char *msgtype )
@@ -318,7 +401,7 @@ static void __winetest_cdecl winetest_print_context( const char *msgtype )
winetest_printf( "%s", msgtype );
for (i = 0; i < data->context_count; ++i)
- printf( "%s: ", data->context[i] );
+ __winetest_printf( "%s: ", data->context[i] );
}
void winetest_subtest( const char* name )
@@ -372,7 +455,7 @@ int winetest_vok( int condition, const char *msg, __winetest_va_list args )
if (condition)
{
winetest_print_context( "Test succeeded inside todo block: " );
- vprintf(msg, args);
+ __winetest_vprintf(msg, args);
InterlockedIncrement(&todo_failures);
return 0;
}
@@ -384,7 +467,7 @@ int winetest_vok( int condition, const char *msg, __winetest_va_list args )
if (winetest_debug > 0)
{
winetest_print_context( "Test marked todo: " );
- vprintf(msg, args);
+ __winetest_vprintf(msg, args);
}
InterlockedIncrement(&todo_successes);
}
@@ -398,17 +481,18 @@ int winetest_vok( int condition, const char *msg, __winetest_va_list args )
if (!condition)
{
winetest_print_context( "Test failed: " );
- vprintf(msg, args);
+ __winetest_vprintf(msg, args);
InterlockedIncrement(&failures);
return 0;
}
else
{
- if (winetest_report_success ||
- (winetest_time && GetTickCount() >= winetest_last_time + 1000))
- {
+ if (winetest_report_success)
winetest_printf("Test succeeded\n");
- }
+#ifndef WINETEST_KERNEL
+ else if (winetest_time && GetTickCount() >= winetest_last_time + 1000)
+ winetest_printf("Test succeeded\n");
+#endif /* WINETEST_KERNEL */
InterlockedIncrement(&successes);
return 1;
}
@@ -434,7 +518,7 @@ void __winetest_cdecl winetest_trace( const char *msg, ... )
{
winetest_print_context( "" );
__winetest_va_start(valist, msg);
- vprintf( msg, valist );
+ __winetest_vprintf( msg, valist );
__winetest_va_end(valist);
}
else
@@ -446,7 +530,7 @@ void winetest_vskip( const char *msg, __winetest_va_list args )
if (winetest_add_line() < winetest_mute_threshold)
{
winetest_print_context( "Tests skipped: " );
- vprintf(msg, args);
+ __winetest_vprintf(msg, args);
InterlockedIncrement(&skipped);
}
else
@@ -533,6 +617,155 @@ void winetest_add_failures( LONG new_failures )
InterlockedIncrement( &failures );
}
+struct winetest_kernel_data
+{
+ char winetest_platform[256];
+ int running_under_wine;
+ int winetest_report_success;
+ int winetest_debug;
+ int failures;
+ int todo_failures;
+};
+
+#ifdef WINETEST_KERNEL
+
+static int running_under_wine;
+
+static inline NTSTATUS winetest_init(void)
+{
+ const struct winetest_kernel_data *data;
+ SIZE_T size = sizeof(*data);
+ OBJECT_ATTRIBUTES attr;
+ UNICODE_STRING string;
+ IO_STATUS_BLOCK io;
+ void *addr = NULL;
+ HANDLE section;
+ NTSTATUS ret;
+
+ KeInitializeSpinLock(&tls_data_lock);
+
+ RtlInitUnicodeString(&string, L"\\BaseNamedObjects\\winetest_kernel_section");
+ /* OBJ_KERNEL_HANDLE is necessary for the file to be accessible from system threads */
+ InitializeObjectAttributes(&attr, &string, OBJ_CASE_INSENSITIVE | OBJ_KERNEL_HANDLE, 0, NULL);
+ if ((ret = ZwOpenSection(§ion, SECTION_MAP_READ, &attr)))
+ return ret;
+
+ if ((ret = ZwMapViewOfSection(section, NtCurrentProcess(), &addr,
+ 0, 0, NULL, &size, ViewUnmap, 0, PAGE_READONLY)))
+ {
+ ZwClose(okfile);
+ ZwClose(section);
+ return ret;
+ }
+ data = addr;
+ running_under_wine = data->running_under_wine;
+ winetest_debug = data->winetest_debug;
+ winetest_report_success = data->winetest_report_success;
+ strcpy(winetest_platform_buf, data->winetest_platform);
+
+ ZwUnmapViewOfSection(NtCurrentProcess(), addr);
+ ZwClose(section);
+
+ RtlInitUnicodeString(&string, L"\\??\\C:\\windows\\winetest_kernel_okfile");
+ return ZwOpenFile(&okfile, FILE_APPEND_DATA | SYNCHRONIZE, &attr, &io,
+ FILE_SHARE_READ | FILE_SHARE_WRITE, FILE_SYNCHRONOUS_IO_NONALERT);
+}
+
+static inline void winetest_cleanup(void)
+{
+ struct winetest_kernel_data *data;
+ SIZE_T size = sizeof(*data);
+ OBJECT_ATTRIBUTES attr;
+ UNICODE_STRING string;
+ void *addr = NULL;
+ HANDLE section;
+
+ if (winetest_debug)
+ {
+ if (muted_todo_successes || muted_skipped || muted_traces)
+ __winetest_printf( "%04x:ntoskrnl:%s Silenced %d todos, %d skips and %d traces.\n",
+ (DWORD)(ULONG_PTR)PsGetCurrentProcessId(), winetest_elapsed(),
+ muted_todo_successes, muted_skipped, muted_traces);
+ __winetest_printf( "%04x:ntoskrnl:%s %d tests executed (%d marked as todo, %d %s), %d skipped.\n",
+ (DWORD)(ULONG_PTR)PsGetCurrentProcessId(), winetest_elapsed(),
+ successes + failures + todo_successes + todo_failures,
+ todo_successes, failures + todo_failures,
+ (failures + todo_failures != 1) ? "failures" : "failure",
+ skipped );
+ }
+
+ RtlInitUnicodeString(&string, L"\\BaseNamedObjects\\winetest_kernel_section");
+ /* OBJ_KERNEL_HANDLE is necessary for the file to be accessible from system threads */
+ InitializeObjectAttributes(&attr, &string, OBJ_CASE_INSENSITIVE | OBJ_KERNEL_HANDLE, 0, NULL);
+
+ if (!ZwOpenSection(§ion, SECTION_MAP_READ | SECTION_MAP_WRITE, &attr))
+ {
+ if (!ZwMapViewOfSection(section, NtCurrentProcess(), &addr,
+ 0, 0, NULL, &size, ViewUnmap, 0, PAGE_READWRITE))
+ {
+ data = addr;
+
+ InterlockedExchangeAdd(&data->failures, failures);
+ InterlockedExchangeAdd(&data->todo_failures, todo_failures);
+
+ ZwUnmapViewOfSection(NtCurrentProcess(), addr);
+ }
+ ZwClose(section);
+ }
+
+ ZwClose(okfile);
+}
+
+#else /* WINETEST_KERNEL */
+
+static HANDLE winetest_mapping;
+static struct winetest_kernel_data *kernel_data;
+
+void winetest_kernel_init(void)
+{
+ winetest_mapping = CreateFileMappingA(INVALID_HANDLE_VALUE, NULL, PAGE_READWRITE, 0,
+ sizeof(*kernel_data), "Global\\winetest_kernel_section");
+ ok(!!winetest_mapping, "got error %u\n", GetLastError());
+ kernel_data = MapViewOfFile(winetest_mapping, FILE_MAP_READ | FILE_MAP_WRITE, 0, 0, 1024);
+ ok(strlen(winetest_platform) < 256, "winetest_platform expectedly large!\n");
+ strcpy(kernel_data->winetest_platform, winetest_platform);
+ kernel_data->running_under_wine = !strcmp(winetest_platform, "wine");
+ kernel_data->winetest_report_success = winetest_report_success;
+ kernel_data->winetest_debug = winetest_debug;
+
+ okfile = CreateFileA("C:\\windows\\winetest_kernel_okfile", GENERIC_READ | GENERIC_WRITE,
+ FILE_SHARE_READ | FILE_SHARE_WRITE, NULL, CREATE_ALWAYS, 0, NULL);
+ ok(okfile != INVALID_HANDLE_VALUE, "failed to create file, error %u\n", GetLastError());
+}
+
+void winetest_kernel_check(void)
+{
+ char buffer[512];
+ DWORD size;
+
+ SetFilePointer(okfile, 0, NULL, FILE_BEGIN);
+
+ do
+ {
+ ReadFile(okfile, buffer, sizeof(buffer), &size, NULL);
+ printf("%.*s", size, buffer);
+ } while (size == sizeof(buffer));
+
+ SetFilePointer(okfile, 0, NULL, FILE_BEGIN);
+ SetEndOfFile(okfile);
+
+ InterlockedExchangeAdd(&failures, InterlockedExchange(&kernel_data->failures, 0));
+ InterlockedExchangeAdd(&todo_failures, InterlockedExchange(&kernel_data->todo_failures, 0));
+}
+
+void winetest_kernel_cleanup(void)
+{
+ UnmapViewOfFile(kernel_data);
+ CloseHandle(winetest_mapping);
+ CloseHandle(okfile);
+ DeleteFileA("C:\\windows\\winetest_kernel_okfile");
+}
+
void winetest_wait_child_process( HANDLE process )
{
DWORD ret;
@@ -702,6 +935,7 @@ int main( int argc, char **argv )
return run_test(argv[1]);
}
+#endif /* WINETEST_KERNEL */
#endif /* STANDALONE */
#endif /* __WINE_WINE_TEST_H */
--
2.32.0