From: Ally Sommers <dropbear.sh(a)gmail.com>
---
dlls/ws2_32/tests/sock.c | 292 +++++++++++++++++++++++++++++++++++++++
1 file changed, 292 insertions(+)
diff --git a/dlls/ws2_32/tests/sock.c b/dlls/ws2_32/tests/sock.c
index 6954b3e077a..e76b65202f0 100644
--- a/dlls/ws2_32/tests/sock.c
+++ b/dlls/ws2_32/tests/sock.c
@@ -29,6 +29,7 @@
#include <iphlpapi.h>
#include <ws2tcpip.h>
#include <wsipx.h>
+#include <afunix.h>
#include <wsnwlink.h>
#include <mswsock.h>
#include <mstcpip.h>
@@ -14167,6 +14168,296 @@ static void test_select_after_WSAEventSelect(void)
closesocket(client);
}
+static void test_afunix(void)
+{
+ SOCKET listener, client, server = 0;
+ SOCKADDR_UN addr = { AF_UNIX, "test_afunix.sock" };
+ char serverBuf[] = "ws2_32/AF_UNIX socket test";
+ char clientBuf[sizeof(serverBuf)] = { 0 };
+
+ char paths[4][sizeof(addr.sun_path)] = { "./tmp.sock",
"../tmp.sock" };
+ char dosPath[sizeof(addr.sun_path)];
+ WCHAR dosWidePath[sizeof(addr.sun_path)];
+ UNICODE_STRING ntPath = { 0 };
+ SOCKADDR_UN outAddr = { 0 };
+ int outAddrSize = sizeof(outAddr);
+ SOCKADDR_UN truncatedAddr = { 0 };
+ ULONG zero = 0;
+ ULONG one = 1;
+ int ret;
+
+ /* Test connection and send/recv */
+ listener = socket(AF_UNIX, SOCK_STREAM, 0);
+ if (listener == INVALID_SOCKET && GetLastError() == WSAEAFNOSUPPORT)
+ {
+ win_skip("AF_UNIX sockets are unsupported, skipping...\n");
+ return;
+ }
+
+ ok(listener != INVALID_SOCKET, "Could not create Unix socket: %lu\n",
+ GetLastError());
+
+ ret = bind(listener, (SOCKADDR *)&addr, 0);
+ ok(ret && GetLastError() == WSAEFAULT, "Incorrect error: %lu\n",
GetLastError());
+ ret = bind(listener, (SOCKADDR *)&addr, 2);
+ ok(!ret, "Could not bind Unix socket: %lu\n", GetLastError());
+ ret = listen(listener, 1);
+ ok(!ret, "Could not listen on Unix socket: %lu\n", GetLastError());
+ closesocket(listener);
+
+ listener = socket(AF_UNIX, SOCK_STREAM, 0);
+ ok(listener != INVALID_SOCKET, "Could not create Unix socket: %lu\n",
+ GetLastError());
+ ret = bind(listener, (SOCKADDR *)&addr, 3);
+ ok(!ret, "Could not bind Unix socket: %lu\n", GetLastError());
+
+ memcpy(&truncatedAddr, &addr, 3);
+ ret = getsockname(listener, (SOCKADDR *)&outAddr, &outAddrSize);
+ ok(!ret, "Could not get info on Unix socket: %lu\n", GetLastError());
+ ok(!memcmp(truncatedAddr.sun_path, outAddr.sun_path, sizeof(addr.sun_path)),
+ "getsockname returned incorrect path '%s' for provided path
'%s'\n",
+ outAddr.sun_path,
+ truncatedAddr.sun_path);
+ ok(outAddrSize == sizeof(outAddr.sun_family) + strlen(outAddr.sun_path) + 1,
+ "getsockname returned incorrect size '%d' for provided path
'%s'\n",
+ outAddrSize,
+ truncatedAddr.sun_path);
+ closesocket(listener);
+ ret = DeleteFileA(truncatedAddr.sun_path);
+ ok(ret, "DeleteFileA on socket file failed: %lu\n", GetLastError());
+ ok(GetFileAttributesA(truncatedAddr.sun_path) == INVALID_FILE_ATTRIBUTES &&
+ GetLastError() == ERROR_FILE_NOT_FOUND,
+ "Failed to delete socket file at path '%s'\n",
+ truncatedAddr.sun_path);
+
+ listener = socket(AF_UNIX, SOCK_STREAM, 0);
+ ok(listener != INVALID_SOCKET, "Could not create Unix socket: %lu\n",
+ GetLastError());
+
+ ret = bind(listener, (SOCKADDR *)&addr, sizeof(SOCKADDR_UN));
+ ok(!ret, "Could not bind Unix socket: %lu\n", GetLastError());
+
+ ret = listen(listener, 1);
+ ok(!ret, "Could not listen on Unix socket: %lu\n", GetLastError());
+
+ client = socket(AF_UNIX, SOCK_STREAM, 0);
+ ok(client != INVALID_SOCKET, "Failed to create second Unix socket: %lu\n",
+ GetLastError());
+
+ ret = ioctlsocket(client, FIONBIO, &one);
+ ok(!ret, "Could not set AF_UNIX socket to nonblocking: %lu; skipping
connection\n", GetLastError());
+ if (!ret)
+ {
+ ret = connect(client, (SOCKADDR *)&addr, sizeof(addr));
+ ok(!ret || (ret == SOCKET_ERROR && GetLastError() == WSAEWOULDBLOCK),
+ "Error when connecting to Unix socket: %lu\n",
+ GetLastError());
+ server = accept(listener, NULL, NULL);
+ ok(server != INVALID_SOCKET, "Could not accept Unix socket connection:
%lu\n",
+ GetLastError());
+ ret = ioctlsocket(client, FIONBIO, &zero);
+ ok(!ret, "Could not set AF_UNIX socket to blocking: %lu\n",
GetLastError());
+ }
+
+ ret = send(server, serverBuf, sizeof(serverBuf), 0);
+ ok(ret == sizeof(serverBuf), "Incorrect return value from send: %d\n",
ret);
+ ret = recv(client, clientBuf, sizeof(serverBuf), 0);
+ ok(ret == sizeof(serverBuf), "Incorrect return value from recv: %d\n",
ret);
+ ok(!memcmp(serverBuf, clientBuf, sizeof(serverBuf)), "Data mismatch over Unix
socket\n");
+
+ memset(clientBuf, 0, sizeof(clientBuf));
+
+ ret = sendto(server, serverBuf, sizeof(serverBuf), 0, NULL, 0);
+ ok(ret == sizeof(serverBuf), "Incorrect return value from sendto: %d\n",
ret);
+ ret = recvfrom(client, clientBuf, sizeof(serverBuf), 0, NULL, 0);
+ ok(ret == sizeof(serverBuf), "Incorrect return value from recvfrom: %d\n",
ret);
+ ok(!memcmp(serverBuf, clientBuf, sizeof(serverBuf)), "Data mismatch over Unix
socket\n");
+
+ memset(serverBuf, 0, sizeof(serverBuf));
+
+ ret = send(client, clientBuf, sizeof(clientBuf), 0);
+ ok(ret == sizeof(clientBuf), "Incorrect return value from send: %d\n",
ret);
+ ret = recv(server, serverBuf, sizeof(clientBuf), 0);
+ ok(ret == sizeof(serverBuf), "Incorrect return value from recv: %d\n",
ret);
+ ok(!memcmp(serverBuf, clientBuf, sizeof(clientBuf)), "Data mismatch over Unix
socket\n");
+
+ memset(serverBuf, 0, sizeof(serverBuf));
+
+ ret = sendto(client, clientBuf, sizeof(clientBuf), 0, NULL, 0);
+ ok(ret == sizeof(clientBuf), "Incorrect return value from sendto: %d\n",
ret);
+ ret = recvfrom(server, serverBuf, sizeof(clientBuf), 0, NULL, 0);
+ ok(ret == sizeof(serverBuf), "Incorrect return value from recvfrom: %d\n",
ret);
+ ok(!memcmp(serverBuf, clientBuf, sizeof(clientBuf)), "Data mismatch over Unix
socket\n");
+
+ closesocket(listener);
+ closesocket(client);
+ closesocket(server);
+
+ /* Test socket file deletion */
+ ret = DeleteFileA("test_afunix.sock");
+ ok(ret, "DeleteFileA on socket file failed: %lu\n", GetLastError());
+ ok(GetFileAttributesA("test_afunix.sock") == INVALID_FILE_ATTRIBUTES
&&
+ GetLastError() == ERROR_FILE_NOT_FOUND,
+ "Failed to delete socket file at path '%s'\n",
+ addr.sun_path);
+
+ /* Test failure modes */
+ listener = socket(AF_UNIX, SOCK_STREAM, 0);
+ ok(listener != INVALID_SOCKET, "Could not create Unix socket: %lu\n",
+ GetLastError());
+ ret = bind(listener, (SOCKADDR *)&addr, sizeof(SOCKADDR_UN));
+ ok(!ret, "Could not bind Unix socket to path '%s': %lu\n",
addr.sun_path, GetLastError());
+ closesocket(listener);
+ listener = socket(AF_UNIX, SOCK_STREAM, 0);
+ ok(listener != INVALID_SOCKET, "Could not create Unix socket: %lu\n",
+ GetLastError());
+ ret = bind(listener, (SOCKADDR *)&addr, sizeof(SOCKADDR_UN));
+ ok(ret && GetLastError() == WSAEADDRINUSE,
+ "Bound Unix socket to path '%s' despite existing socket file:
%lu\n",
+ addr.sun_path,
+ GetLastError());
+ closesocket(listener);
+ ret = DeleteFileA(addr.sun_path);
+ ok(ret, "DeleteFileA on socket file failed: %lu\n", GetLastError());
+ ok(GetFileAttributesA("test_afunix.sock") == INVALID_FILE_ATTRIBUTES
&&
+ GetLastError() == ERROR_FILE_NOT_FOUND,
+ "Failed to delete socket file at path '%s'\n",
+ addr.sun_path);
+
+ /* Test different path types (relative, NT, etc.) */
+ GetTempPathA(sizeof(paths[0]) - 1, paths[2]);
+ strcat(paths[2], "tmp.sock");
+ MultiByteToWideChar(CP_ACP, 0, paths[2], -1, dosWidePath, sizeof(dosPath));
+ RtlDosPathNameToNtPathName_U(dosWidePath, &ntPath, NULL, NULL);
+ RtlUnicodeToMultiByteN(paths[3], sizeof(addr.sun_path) - 1, NULL, ntPath.Buffer,
ntPath.Length);
+
+ for (int i = 0; i < sizeof(paths) / sizeof(paths[0]); i++)
+ {
+ memcpy(addr.sun_path, paths[i], sizeof(paths[i]));
+
+ listener = socket(AF_UNIX, SOCK_STREAM, 0);
+ ok(listener != INVALID_SOCKET, "Could not create Unix socket: %lu\n",
+ GetLastError());
+
+ ret = bind(listener, (SOCKADDR *)&addr, sizeof(SOCKADDR_UN));
+ ok(!ret, "Could not bind Unix socket to path '%s': %lu\n",
addr.sun_path, GetLastError());
+
+ ret = listen(listener, 1);
+ ok(!ret, "Could not listen on Unix socket: %lu\n", GetLastError());
+
+ client = socket(AF_UNIX, SOCK_STREAM, 0);
+ ok(client != INVALID_SOCKET, "Failed to create second Unix socket:
%lu\n",
+ GetLastError());
+
+ ret = ioctlsocket(client, FIONBIO, &one);
+ ok(!ret, "Could not set AF_UNIX socket to nonblocking: %lu; skipping
connection\n", GetLastError());
+ if (!ret)
+ {
+ ret = connect(client, (SOCKADDR *)&addr, sizeof(addr));
+ ok(!ret || (ret == SOCKET_ERROR && GetLastError() ==
WSAEWOULDBLOCK),
+ "Error when connecting to Unix socket: %lu\n",
+ GetLastError());
+ server = accept(listener, NULL, NULL);
+ ok(server != INVALID_SOCKET, "Could not accept Unix socket connection:
%lu\n",
+ GetLastError());
+ ret = ioctlsocket(client, FIONBIO, &zero);
+ ok(!ret, "Could not set AF_UNIX socket to blocking: %lu\n",
GetLastError());
+ }
+
+ memset(&outAddr, 0, sizeof(outAddr));
+ outAddrSize = sizeof(outAddr);
+ ret = getsockname(listener, (SOCKADDR *)&outAddr, &outAddrSize);
+ ok(!ret, "Could not get info on Unix socket: %lu\n", GetLastError());
+ ok(!memcmp(addr.sun_path, outAddr.sun_path, sizeof(addr.sun_path)),
+ "getsockname returned incorrect path '%s' for provided path
'%s'\n",
+ outAddr.sun_path,
+ addr.sun_path);
+ ok(outAddrSize == sizeof(outAddr.sun_family) + strlen(outAddr.sun_path) + 1,
+ "getsockname returned incorrect size '%d' for provided path
'%s'\n",
+ outAddrSize,
+ addr.sun_path);
+
+ memset(&outAddr, 0, sizeof(outAddr));
+ outAddrSize = sizeof(outAddr);
+ ret = getsockname(client, (SOCKADDR *)&outAddr, &outAddrSize);
+ ok(!ret, "Could not get info on Unix socket: %lu\n", GetLastError());
+ ok(!memcmp((char[108]){0}, outAddr.sun_path, sizeof(addr.sun_path)),
+ "getsockname returned incorrect path '%s' for provided path
'%s'\n",
+ outAddr.sun_path,
+ addr.sun_path);
+ ok(outAddrSize == sizeof(outAddr),
+ "getsockname returned incorrect size '%d' for provided path
'%s'\n",
+ outAddrSize,
+ addr.sun_path);
+
+ memset(&outAddr, 0, sizeof(outAddr));
+ outAddrSize = sizeof(outAddr);
+ ret = getsockname(server, (SOCKADDR *)&outAddr, &outAddrSize);
+ ok(!ret, "Could not get info on Unix socket: %lu\n", GetLastError());
+ ok(!memcmp(addr.sun_path, outAddr.sun_path, sizeof(addr.sun_path)),
+ "getsockname returned incorrect path '%s' for provided path
'%s'\n",
+ outAddr.sun_path,
+ addr.sun_path);
+ ok(outAddrSize == sizeof(outAddr.sun_family) + strlen(outAddr.sun_path) + 1,
+ "getsockname returned incorrect size '%d' for provided path
'%s'\n",
+ outAddrSize,
+ addr.sun_path);
+
+ memset(&outAddr, 0, sizeof(outAddr));
+ outAddrSize = sizeof(outAddr);
+ ret = getpeername(listener, (SOCKADDR *)&outAddr, &outAddrSize);
+ ok(ret == -1, "Got info on Unix socket: %lu\n", GetLastError());
+ ok(GetLastError() == WSAENOTCONN,
+ "Incorrect error returned from getpeername on Unix socket: %ld\n",
+ GetLastError());
+ ok(!memcmp((char[108]){0}, outAddr.sun_path, sizeof(addr.sun_path)),
+ "getpeername returned incorrect path '%s' for provided path
'%s'\n",
+ outAddr.sun_path,
+ addr.sun_path);
+ ok(outAddrSize == sizeof(outAddr),
+ "getpeername returned incorrect size '%d' for provided path
'%s'\n",
+ outAddrSize,
+ addr.sun_path);
+
+ memset(&outAddr, 0, sizeof(outAddr));
+ outAddrSize = sizeof(outAddr);
+ ret = getpeername(client, (SOCKADDR *)&outAddr, &outAddrSize);
+ ok(!ret, "Could not get info on Unix socket: %lu\n", GetLastError());
+ ok(!memcmp(addr.sun_path, outAddr.sun_path, sizeof(addr.sun_path)),
+ "getpeername returned incorrect path '%s' for provided path
'%s'\n",
+ outAddr.sun_path,
+ addr.sun_path);
+ ok(outAddrSize == sizeof(outAddr),
+ "getpeername returned incorrect size '%d' for provided path
'%s'\n",
+ outAddrSize,
+ addr.sun_path);
+
+ memset(&outAddr, 0, sizeof(outAddr));
+ outAddrSize = sizeof(outAddr);
+ ret = getpeername(server, (SOCKADDR *)&outAddr, &outAddrSize);
+ ok(!ret, "Could not get info on Unix socket: %lu\n", GetLastError());
+ ok(!memcmp((char[108]){0}, outAddr.sun_path, sizeof(addr.sun_path)),
+ "getpeername returned incorrect path '%s' for provided path
'%s'\n",
+ outAddr.sun_path,
+ addr.sun_path);
+ ok(outAddrSize == sizeof(outAddr),
+ "getpeername returned incorrect size '%d' for provided path
'%s'\n",
+ outAddrSize,
+ addr.sun_path);
+
+ closesocket(listener);
+ closesocket(client);
+ closesocket(server);
+
+ ret = DeleteFileA(addr.sun_path);
+ ok(ret, "DeleteFileA on socket file failed: %lu\n", GetLastError());
+ ok(GetFileAttributesA(addr.sun_path) == INVALID_FILE_ATTRIBUTES &&
+ GetLastError() == ERROR_FILE_NOT_FOUND,
+ "Failed to delete socket file at path '%s'\n",
+ addr.sun_path);
+ }
+}
+
START_TEST( sock )
{
int i;
@@ -14249,6 +14540,7 @@ START_TEST( sock )
test_icmp();
test_connect_udp();
test_tcp_sendto_recvfrom();
+ test_afunix();
/* There is apparently an obscure interaction between this test and
* test_WSAGetOverlappedResult().
--
GitLab
https://gitlab.winehq.org/wine/wine/-/merge_requests/2786