[PATCH 3/5] ws2_32/tests: Separate and expand tests for FIONREAD and SIOCATMARK.
Zebediah Figura
z.figura12 at gmail.com
Thu May 27 18:57:31 CDT 2021
Signed-off-by: Zebediah Figura <z.figura12 at gmail.com>
---
dlls/ws2_32/tests/sock.c | 379 +++++++++++++++++++++++++++------------
1 file changed, 260 insertions(+), 119 deletions(-)
diff --git a/dlls/ws2_32/tests/sock.c b/dlls/ws2_32/tests/sock.c
index f6304c0f5ce..b84ebe88c6a 100644
--- a/dlls/ws2_32/tests/sock.c
+++ b/dlls/ws2_32/tests/sock.c
@@ -3624,54 +3624,273 @@ static void test_getsockname(void)
WSACleanup();
}
+static DWORD apc_error, apc_size;
+static OVERLAPPED *apc_overlapped;
+static unsigned int apc_count;
+
+static void WINAPI socket_apc(DWORD error, DWORD size, OVERLAPPED *overlapped, DWORD flags)
+{
+ ok(!flags, "got flags %#x\n", flags);
+ ++apc_count;
+ apc_error = error;
+ apc_size = size;
+ apc_overlapped = overlapped;
+}
+
+#define check_fionread_siocatmark(a, b, c) check_fionread_siocatmark_(__LINE__, a, b, c, FALSE, FALSE)
+#define check_fionread_siocatmark_todo(a, b, c) check_fionread_siocatmark_(__LINE__, a, b, c, TRUE, TRUE)
+#define check_fionread_siocatmark_todo_oob(a, b, c) check_fionread_siocatmark_(__LINE__, a, b, c, FALSE, TRUE)
+static void check_fionread_siocatmark_(int line, SOCKET s, unsigned int normal, unsigned int oob,
+ BOOL todo_normal, BOOL todo_oob)
+{
+ int ret, value;
+ DWORD size;
+
+ value = 0xdeadbeef;
+ WSASetLastError(0xdeadbeef);
+ ret = WSAIoctl(s, FIONREAD, NULL, 0, &value, sizeof(value), &size, NULL, NULL);
+ ok_(__FILE__, line)(!ret, "expected success\n");
+ todo_wine ok_(__FILE__, line)(!WSAGetLastError(), "got error %u\n", WSAGetLastError());
+ todo_wine_if (todo_normal) ok_(__FILE__, line)(value == normal, "FIONBIO returned %u\n", value);
+
+ value = 0xdeadbeef;
+ WSASetLastError(0xdeadbeef);
+ ret = WSAIoctl(s, SIOCATMARK, NULL, 0, &value, sizeof(value), &size, NULL, NULL);
+ ok_(__FILE__, line)(!ret, "expected success\n");
+ todo_wine ok_(__FILE__, line)(!WSAGetLastError(), "got error %u\n", WSAGetLastError());
+ todo_wine_if (todo_oob) ok_(__FILE__, line)(value == oob, "SIOCATMARK returned %u\n", value);
+}
+
+static void test_fionread_siocatmark(void)
+{
+ const struct sockaddr_in bind_addr = {.sin_family = AF_INET, .sin_addr.s_addr = htonl(INADDR_LOOPBACK)};
+ OVERLAPPED overlapped = {0}, *overlapped_ptr;
+ SOCKET client, server;
+ char buffer[5];
+ int ret, value;
+ ULONG_PTR key;
+ HANDLE port;
+ DWORD size;
+
+ tcp_socketpair(&client, &server);
+ set_blocking(client, FALSE);
+ overlapped.hEvent = CreateEventW(NULL, TRUE, FALSE, NULL);
+
+ WSASetLastError(0xdeadbeef);
+ ret = ioctlsocket(client, FIONREAD, (u_long *)1);
+ ok(ret == -1, "expected failure\n");
+ ok(WSAGetLastError() == WSAEFAULT, "got error %u\n", WSAGetLastError());
+
+ WSASetLastError(0xdeadbeef);
+ ret = ioctlsocket(client, SIOCATMARK, (u_long *)1);
+ ok(ret == -1, "expected failure\n");
+ ok(WSAGetLastError() == WSAEFAULT, "got error %u\n", WSAGetLastError());
+
+ WSASetLastError(0xdeadbeef);
+ ret = WSAIoctl(client, FIONREAD, NULL, 0, &value, sizeof(value), NULL, NULL, NULL);
+ todo_wine ok(ret == -1, "expected failure\n");
+ todo_wine ok(WSAGetLastError() == WSAEFAULT, "got error %u\n", WSAGetLastError());
+
+ WSASetLastError(0xdeadbeef);
+ size = 0xdeadbeef;
+ ret = WSAIoctl(client, FIONREAD, NULL, 0, &value, sizeof(value) - 1, &size, NULL, NULL);
+ ok(ret == -1, "expected failure\n");
+ ok(WSAGetLastError() == WSAEFAULT, "got error %u\n", WSAGetLastError());
+ ok(size == 0xdeadbeef, "got size %u\n", size);
+
+ WSASetLastError(0xdeadbeef);
+ ret = WSAIoctl(client, SIOCATMARK, NULL, 0, &value, sizeof(value), NULL, NULL, NULL);
+ todo_wine ok(ret == -1, "expected failure\n");
+ todo_wine ok(WSAGetLastError() == WSAEFAULT, "got error %u\n", WSAGetLastError());
+
+ WSASetLastError(0xdeadbeef);
+ size = 0xdeadbeef;
+ ret = WSAIoctl(client, SIOCATMARK, NULL, 0, &value, sizeof(value) - 1, &size, NULL, NULL);
+ ok(ret == -1, "expected failure\n");
+ ok(WSAGetLastError() == WSAEFAULT, "got error %u\n", WSAGetLastError());
+ ok(size == 0xdeadbeef, "got size %u\n", size);
+
+ check_fionread_siocatmark(client, 0, TRUE);
+
+ port = CreateIoCompletionPort((HANDLE)client, NULL, 123, 0);
+
+ ret = WSAIoctl(client, FIONREAD, NULL, 0, &value, sizeof(value), NULL, &overlapped, NULL);
+ todo_wine ok(ret == -1, "expected failure\n");
+ todo_wine ok(WSAGetLastError() == WSAEFAULT, "got error %u\n", WSAGetLastError());
+
+ ret = WSAIoctl(client, SIOCATMARK, NULL, 0, &value, sizeof(value), NULL, &overlapped, NULL);
+ todo_wine ok(ret == -1, "expected failure\n");
+ todo_wine ok(WSAGetLastError() == WSAEFAULT, "got error %u\n", WSAGetLastError());
+
+ WSASetLastError(0xdeadbeef);
+ size = 0xdeadbeef;
+ value = 0xdeadbeef;
+ overlapped.Internal = 0xdeadbeef;
+ overlapped.InternalHigh = 0xdeadbeef;
+ ret = WSAIoctl(client, FIONREAD, NULL, 0, &value, sizeof(value), &size, &overlapped, NULL);
+ ok(!ret, "expected success\n");
+ todo_wine ok(!WSAGetLastError(), "got error %u\n", WSAGetLastError());
+ ok(!value, "got %u\n", value);
+ todo_wine ok(size == sizeof(value), "got size %u\n", size);
+ ok(!overlapped.Internal, "got status %#x\n", (NTSTATUS)overlapped.Internal);
+ ok(!overlapped.InternalHigh, "got size %Iu\n", overlapped.InternalHigh);
+
+ ret = GetQueuedCompletionStatus(port, &size, &key, &overlapped_ptr, 0);
+ ok(ret, "got error %u\n", GetLastError());
+ ok(!size, "got size %u\n", size);
+ ok(key == 123, "got key %Iu\n", key);
+ ok(overlapped_ptr == &overlapped, "got overlapped %p\n", overlapped_ptr);
+
+ WSASetLastError(0xdeadbeef);
+ size = 0xdeadbeef;
+ value = 0xdeadbeef;
+ overlapped.Internal = 0xdeadbeef;
+ overlapped.InternalHigh = 0xdeadbeef;
+ ret = WSAIoctl(client, SIOCATMARK, NULL, 0, &value, sizeof(value), &size, &overlapped, NULL);
+ ok(!ret, "expected success\n");
+ todo_wine ok(!WSAGetLastError(), "got error %u\n", WSAGetLastError());
+ ok(value == TRUE, "got %u\n", value);
+ todo_wine ok(size == sizeof(value), "got size %u\n", size);
+ ok(!overlapped.Internal, "got status %#x\n", (NTSTATUS)overlapped.Internal);
+ ok(!overlapped.InternalHigh, "got size %Iu\n", overlapped.InternalHigh);
+
+ ret = GetQueuedCompletionStatus(port, &size, &key, &overlapped_ptr, 0);
+ ok(ret, "got error %u\n", GetLastError());
+ ok(!size, "got size %u\n", size);
+ ok(key == 123, "got key %Iu\n", key);
+ ok(overlapped_ptr == &overlapped, "got overlapped %p\n", overlapped_ptr);
+
+ ret = send(server, "data", 5, 0);
+ ok(ret == 5, "got %d\n", ret);
+
+ check_fionread_siocatmark(client, 5, TRUE);
+
+ ret = send(server, "a", 1, MSG_OOB);
+ ok(ret == 1, "got %d\n", ret);
+
+ check_fionread_siocatmark_todo_oob(client, 5, FALSE);
+
+ ret = send(server, "a", 1, MSG_OOB);
+ ok(ret == 1, "got %d\n", ret);
+
+ check_fionread_siocatmark_todo(client, 5, FALSE);
+
+ ret = recv(client, buffer, 3, 0);
+ ok(ret == 3, "got %d\n", ret);
+
+ check_fionread_siocatmark_todo(client, 2, FALSE);
+
+ ret = recv(client, buffer, 1, MSG_OOB);
+ ok(ret == 1, "got %d\n", ret);
+
+ check_fionread_siocatmark_todo(client, 2, FALSE);
+
+ ret = recv(client, buffer, 5, 0);
+ todo_wine ok(ret == 2, "got %d\n", ret);
+
+ check_fionread_siocatmark(client, 0, FALSE);
+
+ ret = recv(client, buffer, 1, MSG_OOB);
+ todo_wine ok(ret == 1, "got %d\n", ret);
+
+ check_fionread_siocatmark_todo_oob(client, 0, TRUE);
+
+ ret = send(server, "a", 1, MSG_OOB);
+ ok(ret == 1, "got %d\n", ret);
+
+ ret = 1;
+ ret = setsockopt(client, SOL_SOCKET, SO_OOBINLINE, (char *)&ret, sizeof(ret));
+ ok(!ret, "got error %u\n", WSAGetLastError());
+
+ check_fionread_siocatmark_todo_oob(client, 1, FALSE);
+
+ ret = recv(client, buffer, 1, 0);
+ ok(ret == 1, "got %d\n", ret);
+
+ check_fionread_siocatmark(client, 0, TRUE);
+
+ ret = send(server, "a", 1, MSG_OOB);
+ ok(ret == 1, "got %d\n", ret);
+
+ check_fionread_siocatmark(client, 1, TRUE);
+
+ closesocket(client);
+ closesocket(server);
+
+ server = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
+
+ check_fionread_siocatmark(server, 0, TRUE);
+
+ ret = bind(server, (const struct sockaddr *)&bind_addr, sizeof(bind_addr));
+ ok(!ret, "got error %u\n", WSAGetLastError());
+
+ check_fionread_siocatmark(server, 0, TRUE);
+
+ closesocket(server);
+ CloseHandle(overlapped.hEvent);
+
+ /* test with APCs */
+
+ server = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
+
+ ret = WSAIoctl(server, FIONREAD, NULL, 0, &value, sizeof(value), NULL, &overlapped, socket_apc);
+ todo_wine ok(ret == -1, "expected failure\n");
+ todo_wine ok(WSAGetLastError() == WSAEFAULT, "got error %u\n", WSAGetLastError());
+
+ ret = WSAIoctl(server, SIOCATMARK, NULL, 0, &value, sizeof(value), NULL, &overlapped, socket_apc);
+ todo_wine ok(ret == -1, "expected failure\n");
+ todo_wine ok(WSAGetLastError() == WSAEFAULT, "got error %u\n", WSAGetLastError());
+
+ apc_count = 0;
+ size = 0xdeadbeef;
+ ret = WSAIoctl(server, FIONREAD, NULL, 0, &value, sizeof(value), &size, &overlapped, socket_apc);
+ ok(!ret, "expected success\n");
+ todo_wine ok(size == sizeof(value), "got size %u\n", size);
+
+ ret = SleepEx(0, TRUE);
+ todo_wine ok(ret == WAIT_IO_COMPLETION, "got %d\n", ret);
+ if (ret == WAIT_IO_COMPLETION)
+ {
+ ok(apc_count == 1, "APC was called %u times\n", apc_count);
+ ok(!apc_error, "got APC error %u\n", apc_error);
+ ok(!apc_size, "got APC size %u\n", apc_size);
+ ok(apc_overlapped == &overlapped, "got APC overlapped %p\n", apc_overlapped);
+ }
+
+ apc_count = 0;
+ size = 0xdeadbeef;
+ ret = WSAIoctl(server, SIOCATMARK, NULL, 0, &value, sizeof(value), &size, &overlapped, socket_apc);
+ ok(!ret, "expected success\n");
+ todo_wine ok(size == sizeof(value), "got size %u\n", size);
+
+ ret = SleepEx(0, TRUE);
+ todo_wine ok(ret == WAIT_IO_COMPLETION, "got %d\n", ret);
+ if (ret == WAIT_IO_COMPLETION)
+ {
+ ok(apc_count == 1, "APC was called %u times\n", apc_count);
+ ok(!apc_error, "got APC error %u\n", apc_error);
+ ok(!apc_size, "got APC size %u\n", apc_size);
+ ok(apc_overlapped == &overlapped, "got APC overlapped %p\n", apc_overlapped);
+ }
+
+ closesocket(server);
+}
+
static void test_ioctlsocket(void)
{
- SOCKET sock, src, dst;
+ SOCKET sock;
struct tcp_keepalive kalive;
- struct sockaddr_in address;
- int ret, optval;
- static const LONG cmds[] = {FIONBIO, FIONREAD, SIOCATMARK};
- UINT i, bytes_rec;
- char data;
- WSABUF bufs;
+ int ret;
u_long arg = 0;
sock = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
ok(sock != INVALID_SOCKET, "Creating the socket failed: %d\n", WSAGetLastError());
- for(i = 0; i < ARRAY_SIZE(cmds); i++)
- {
- /* broken apps like defcon pass the argp value directly instead of a pointer to it */
- ret = ioctlsocket(sock, cmds[i], (u_long *)1);
- ok(ret == SOCKET_ERROR, "ioctlsocket succeeded unexpectedly\n");
- ret = WSAGetLastError();
- ok(ret == WSAEFAULT, "expected WSAEFAULT, got %d instead\n", ret);
- }
-
- /* A fresh and not connected socket has no urgent data, this test shows
- * that normal(not urgent) data returns a non-zero value for SIOCATMARK. */
-
- ret = ioctlsocket(sock, SIOCATMARK, &arg);
- ok(ret != SOCKET_ERROR, "ioctlsocket failed unexpectedly\n");
- ok(arg, "SIOCATMARK expected a non-zero value\n");
-
- /* when SO_OOBINLINE is set SIOCATMARK must always return TRUE */
- optval = 1;
- ret = setsockopt(sock, SOL_SOCKET, SO_OOBINLINE, (void *)&optval, sizeof(optval));
- ok(ret != SOCKET_ERROR, "setsockopt failed unexpectedly\n");
- arg = 0;
- ret = ioctlsocket(sock, SIOCATMARK, &arg);
- ok(ret != SOCKET_ERROR, "ioctlsocket failed unexpectedly\n");
- ok(arg, "SIOCATMARK expected a non-zero value\n");
-
- /* disable SO_OOBINLINE and get the same old behavior */
- optval = 0;
- ret = setsockopt(sock, SOL_SOCKET, SO_OOBINLINE, (void *)&optval, sizeof(optval));
- ok(ret != SOCKET_ERROR, "setsockopt failed unexpectedly\n");
- arg = 0;
- ret = ioctlsocket(sock, SIOCATMARK, &arg);
- ok(ret != SOCKET_ERROR, "ioctlsocket failed unexpectedly\n");
- ok(arg, "SIOCATMARK expected a non-zero value\n");
+ /* broken apps like defcon pass the argp value directly instead of a pointer to it */
+ ret = ioctlsocket(sock, FIONBIO, (u_long *)1);
+ ok(ret == SOCKET_ERROR, "ioctlsocket succeeded unexpectedly\n");
+ ret = WSAGetLastError();
+ ok(ret == WSAEFAULT, "expected WSAEFAULT, got %d instead\n", ret);
ret = WSAIoctl(sock, SIO_KEEPALIVE_VALS, &arg, 0, NULL, 0, &arg, NULL, NULL);
ok(ret == SOCKET_ERROR, "WSAIoctl succeeded unexpectedly\n");
@@ -3706,85 +3925,6 @@ static void test_ioctlsocket(void)
ok(ret == 0, "WSAIoctl failed unexpectedly\n");
closesocket(sock);
-
- sock = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
- ok(sock != INVALID_SOCKET, "Creating the socket failed: %d\n", WSAGetLastError());
-
- /* test FIONREAD with a fresh and non-connected socket */
- arg = 0xdeadbeef;
- ret = ioctlsocket(sock, FIONREAD, &arg);
- ok(ret == 0, "ioctlsocket failed unexpectedly with error %d\n", WSAGetLastError());
- ok(arg == 0, "expected 0, got %u\n", arg);
-
- memset(&address, 0, sizeof(address));
- address.sin_family = AF_INET;
- address.sin_addr.s_addr = inet_addr( SERVERIP );
- address.sin_port = htons( SERVERPORT );
- ret = bind(sock, (struct sockaddr *)&address, sizeof(address));
- ok(ret == 0, "bind failed unexpectedly with error %d\n", WSAGetLastError());
-
- ret = listen(sock, SOMAXCONN);
- ok(ret == 0, "listen failed unexpectedly with error %d\n", WSAGetLastError());
-
- /* test FIONREAD with listening socket */
- arg = 0xdeadbeef;
- ret = ioctlsocket(sock, FIONREAD, &arg);
- ok(ret == 0, "ioctlsocket failed unexpectedly with error %d\n", WSAGetLastError());
- ok(arg == 0, "expected 0, got %u\n", arg);
-
- closesocket(sock);
-
- tcp_socketpair(&src, &dst);
-
- /* test FIONREAD on TCP sockets */
- optval = 0xdeadbeef;
- ret = WSAIoctl(dst, FIONREAD, NULL, 0, &optval, sizeof(optval), &arg, NULL, NULL);
- ok(ret == 0, "WSAIoctl failed unexpectedly with error %d\n", WSAGetLastError());
- ok(optval == 0, "FIONREAD should have returned 0 bytes, got %d instead\n", optval);
-
- optval = 0xdeadbeef;
- ok(send(src, "TEST", 4, 0) == 4, "failed to send test data\n");
- Sleep(100);
- ret = WSAIoctl(dst, FIONREAD, NULL, 0, &optval, sizeof(optval), &arg, NULL, NULL);
- ok(ret == 0, "WSAIoctl failed unexpectedly with error %d\n", WSAGetLastError());
- ok(optval == 4, "FIONREAD should have returned 4 bytes, got %d instead\n", optval);
-
- /* trying to read from an OOB inlined socket with MSG_OOB results in WSAEINVAL */
- set_blocking(dst, FALSE);
- i = MSG_OOB;
- SetLastError(0xdeadbeef);
- ret = recv(dst, &data, 1, i);
- ok(ret == SOCKET_ERROR, "expected -1, got %d\n", ret);
- ret = GetLastError();
- ok(ret == WSAEWOULDBLOCK, "expected 10035, got %d\n", ret);
- bufs.len = sizeof(char);
- bufs.buf = &data;
- ret = WSARecv(dst, &bufs, 1, &bytes_rec, &i, NULL, NULL);
- ok(ret == SOCKET_ERROR, "expected -1, got %d\n", ret);
- ret = GetLastError();
- ok(ret == WSAEWOULDBLOCK, "expected 10035, got %d\n", ret);
- optval = 1;
- ret = setsockopt(dst, SOL_SOCKET, SO_OOBINLINE, (void *)&optval, sizeof(optval));
- ok(ret != SOCKET_ERROR, "setsockopt failed unexpectedly\n");
- i = MSG_OOB;
- SetLastError(0xdeadbeef);
- ret = recv(dst, &data, 1, i);
- ok(ret == SOCKET_ERROR, "expected SOCKET_ERROR, got %d\n", ret);
- ret = GetLastError();
- ok(ret == WSAEINVAL, "expected 10022, got %d\n", ret);
- bufs.len = sizeof(char);
- bufs.buf = &data;
- ret = WSARecv(dst, &bufs, 1, &bytes_rec, &i, NULL, NULL);
- ok(ret == SOCKET_ERROR, "expected -1, got %d\n", ret);
- ret = GetLastError();
- ok(ret == WSAEINVAL, "expected 10022, got %d\n", ret);
-
- closesocket(dst);
- optval = 0xdeadbeef;
- ret = WSAIoctl(dst, FIONREAD, NULL, 0, &optval, sizeof(optval), &arg, NULL, NULL);
- ok(ret == SOCKET_ERROR, "WSAIoctl succeeded unexpectedly\n");
- ok(optval == 0xdeadbeef, "FIONREAD should not have changed last error, got %d instead\n", optval);
- closesocket(src);
}
static BOOL drain_pause = FALSE;
@@ -10031,6 +10171,7 @@ START_TEST( sock )
test_accept();
test_getpeername();
test_getsockname();
+ test_fionread_siocatmark();
test_ioctlsocket();
test_WSASendMsg();
--
2.30.2
More information about the wine-devel
mailing list