Zebediah Figura : ws2_32/tests: Add some tests for NtReadFile() and NtWriteFile() on sockets.
Alexandre Julliard
julliard at winehq.org
Thu Jul 14 16:59:25 CDT 2022
Module: wine
Branch: master
Commit: cc879c25d7347ceb58da48f6e6317f13268ea63c
URL: https://gitlab.winehq.org/wine/wine/-/commit/cc879c25d7347ceb58da48f6e6317f13268ea63c
Author: Zebediah Figura <zfigura at codeweavers.com>
Date: Sun May 29 12:42:49 2022 -0500
ws2_32/tests: Add some tests for NtReadFile() and NtWriteFile() on sockets.
---
dlls/ws2_32/tests/afd.c | 154 +++++++++++++++++++++++++++++++++++++++++++++++-
1 file changed, 151 insertions(+), 3 deletions(-)
diff --git a/dlls/ws2_32/tests/afd.c b/dlls/ws2_32/tests/afd.c
index f84e7084a27..22ccdd0adeb 100644
--- a/dlls/ws2_32/tests/afd.c
+++ b/dlls/ws2_32/tests/afd.c
@@ -33,16 +33,16 @@
#define TIMEOUT_INFINITE _I64_MAX
-static void tcp_socketpair(SOCKET *src, SOCKET *dst)
+static void tcp_socketpair_flags(SOCKET *src, SOCKET *dst, DWORD flags)
{
SOCKET server = INVALID_SOCKET;
struct sockaddr_in addr;
int len, ret;
- *src = WSASocketW(AF_INET, SOCK_STREAM, IPPROTO_TCP, NULL, 0, WSA_FLAG_OVERLAPPED);
+ *src = WSASocketW(AF_INET, SOCK_STREAM, IPPROTO_TCP, NULL, 0, flags);
ok(*src != INVALID_SOCKET, "failed to create socket, error %u\n", WSAGetLastError());
- server = WSASocketW(AF_INET, SOCK_STREAM, IPPROTO_TCP, NULL, 0, WSA_FLAG_OVERLAPPED);
+ server = WSASocketW(AF_INET, SOCK_STREAM, IPPROTO_TCP, NULL, 0, flags);
ok(server != INVALID_SOCKET, "failed to create socket, error %u\n", WSAGetLastError());
memset(&addr, 0, sizeof(addr));
@@ -68,6 +68,11 @@ static void tcp_socketpair(SOCKET *src, SOCKET *dst)
closesocket(server);
}
+static void tcp_socketpair(SOCKET *src, SOCKET *dst)
+{
+ tcp_socketpair_flags(src, dst, WSA_FLAG_OVERLAPPED);
+}
+
static void set_blocking(SOCKET s, ULONG blocking)
{
int ret;
@@ -2575,6 +2580,148 @@ static void test_async_thread_termination(void)
closesocket(listener);
}
+static DWORD WINAPI sync_read_file_thread(void *arg)
+{
+ HANDLE server = arg;
+ IO_STATUS_BLOCK io;
+ char buffer[5];
+ NTSTATUS ret;
+
+ memset(buffer, 0xcc, sizeof(buffer));
+ memset(&io, 0xcc, sizeof(io));
+ ret = NtReadFile(server, NULL, NULL, NULL, &io, buffer, sizeof(buffer), NULL, NULL);
+ ok(!ret, "got status %#lx\n", ret);
+ ok(!io.Status, "got status %#lx\n", io.Status);
+ ok(io.Information == 4, "got size %Iu\n", io.Information);
+ ok(!memcmp(buffer, "data", 4), "got data %s\n", debugstr_an(buffer, io.Information));
+
+ return 0;
+}
+
+static void test_read_write(void)
+{
+ WSANETWORKEVENTS events;
+ IO_STATUS_BLOCK io, io2;
+ SOCKET client, server;
+ LARGE_INTEGER offset;
+ HANDLE event, thread;
+ char buffer[5];
+ NTSTATUS ret;
+
+ event = CreateEventA(NULL, TRUE, FALSE, NULL);
+
+ tcp_socketpair_flags(&client, &server, 0);
+ set_blocking(server, FALSE);
+
+ memset(&io, 0xcc, sizeof(io));
+ ret = NtWriteFile((HANDLE)client, NULL, NULL, NULL, &io, "data", 4, NULL, NULL);
+ ok(!ret, "got status %#lx\n", ret);
+ ok(!io.Status, "got status %#lx\n", io.Status);
+ ok(io.Information == 4, "got size %Iu\n", io.Information);
+
+ memset(buffer, 0xcc, sizeof(buffer));
+ memset(&io, 0xcc, sizeof(io));
+ ret = NtReadFile((HANDLE)server, NULL, NULL, NULL, &io, buffer, sizeof(buffer), NULL, NULL);
+ ok(!ret, "got status %#lx\n", ret);
+ ok(!io.Status, "got status %#lx\n", io.Status);
+ ok(io.Information == 4, "got size %Iu\n", io.Information);
+ ok(!memcmp(buffer, "data", 4), "got data %s\n", debugstr_an(buffer, io.Information));
+
+ ret = send(server, "data", 4, 0);
+ ok(ret == 4, "got %ld\n", ret);
+
+ ret = WSAEventSelect(client, event, FD_READ);
+ ok(!ret, "got error %lu\n", GetLastError());
+
+ ret = WSAEnumNetworkEvents(client, event, &events);
+ ok(!ret, "got error %lu\n", GetLastError());
+ ok(events.lNetworkEvents == FD_READ, "got events %#lx\n", events.lNetworkEvents);
+
+ memset(buffer, 0xcc, sizeof(buffer));
+ ret = NtReadFile((HANDLE)client, NULL, NULL, NULL, &io, buffer, 1, NULL, NULL);
+ ok(!ret, "got status %#lx\n", ret);
+ ok(io.Information == 1, "got size %Iu\n", io.Information);
+ ok(buffer[0] == 'd', "got data %s\n", debugstr_an(buffer, io.Information));
+
+ ret = WSAEnumNetworkEvents(client, event, &events);
+ ok(!ret, "got error %lu\n", GetLastError());
+ todo_wine ok(events.lNetworkEvents == FD_READ, "got events %#lx\n", events.lNetworkEvents);
+
+ memset(buffer, 0xcc, sizeof(buffer));
+ ret = NtReadFile((HANDLE)client, NULL, NULL, NULL, &io, buffer, sizeof(buffer), NULL, NULL);
+ ok(!ret, "got status %#lx\n", ret);
+ ok(io.Information == 3, "got size %Iu\n", io.Information);
+ ok(!memcmp(buffer, "ata", 3), "got data %s\n", debugstr_an(buffer, io.Information));
+
+ /* NtReadFile always blocks, even when the socket is non-overlapped and nonblocking */
+
+ thread = CreateThread(NULL, 0, sync_read_file_thread, (void *)server, 0, NULL);
+ ret = WaitForSingleObject(thread, 100);
+ ok(ret == WAIT_TIMEOUT, "got %ld\n", ret);
+
+ ret = NtWriteFile((HANDLE)client, NULL, NULL, NULL, &io, "data", 4, NULL, NULL);
+ ok(!ret, "got status %#lx\n", ret);
+
+ ret = WaitForSingleObject(thread, 1000);
+ ok(!ret, "got %ld\n", ret);
+ CloseHandle(thread);
+
+ closesocket(server);
+ closesocket(client);
+
+ tcp_socketpair(&client, &server);
+
+ ret = NtReadFile((HANDLE)server, event, NULL, NULL, &io, buffer, sizeof(buffer), NULL, NULL);
+ todo_wine ok(ret == STATUS_INVALID_PARAMETER, "got status %#lx\n", ret);
+ if (ret == STATUS_PENDING)
+ {
+ CancelIo((HANDLE)server);
+ ret = WaitForSingleObject(event, 100);
+ ok(!ret, "wait timed out\n");
+ }
+
+ offset.QuadPart = -1;
+ ret = NtReadFile((HANDLE)server, event, NULL, NULL, &io, buffer, sizeof(buffer), &offset, NULL);
+ todo_wine ok(ret == STATUS_INVALID_PARAMETER, "got status %#lx\n", ret);
+ if (ret == STATUS_PENDING)
+ {
+ CancelIo((HANDLE)server);
+ ret = WaitForSingleObject(event, 100);
+ ok(!ret, "wait timed out\n");
+ }
+
+ memset(buffer, 0xcc, sizeof(buffer));
+ memset(&io, 0xcc, sizeof(io));
+ offset.QuadPart = 1;
+ ret = NtReadFile((HANDLE)server, event, NULL, NULL, &io, buffer, sizeof(buffer), &offset, NULL);
+ ok(ret == STATUS_PENDING, "got status %#lx\n", ret);
+
+ ret = NtWriteFile((HANDLE)client, NULL, NULL, NULL, &io2, "data", 4, NULL, NULL);
+ todo_wine ok(ret == STATUS_INVALID_PARAMETER, "got status %#lx\n", ret);
+
+ offset.QuadPart = -3;
+ ret = NtWriteFile((HANDLE)client, NULL, NULL, NULL, &io2, "data", 4, &offset, NULL);
+ todo_wine ok(ret == STATUS_INVALID_PARAMETER, "got status %#lx\n", ret);
+
+ memset(&io2, 0xcc, sizeof(io2));
+ offset.QuadPart = 2;
+ ret = NtWriteFile((HANDLE)client, NULL, NULL, NULL, &io2, "data", 4, &offset, NULL);
+ ok(!ret, "got status %#lx\n", ret);
+ ok(!io2.Status, "got status %#lx\n", io2.Status);
+ ok(io2.Information == 4, "got size %Iu\n", io2.Information);
+
+ ret = WaitForSingleObject(event, 1000);
+ ok(!ret, "wait timed out\n");
+ ok(!io.Status, "got status %#lx\n", io.Status);
+ ok(io.Information == 4, "got size %Iu\n", io.Information);
+ ok(!memcmp(buffer, "data", 4), "got data %s\n", debugstr_an(buffer, io.Information));
+
+ closesocket(server);
+ closesocket(client);
+
+ CloseHandle(event);
+}
+
START_TEST(afd)
{
WSADATA data;
@@ -2593,6 +2740,7 @@ START_TEST(afd)
test_bind();
test_getsockname();
test_async_thread_termination();
+ test_read_write();
WSACleanup();
}
More information about the wine-cvs
mailing list