From: Ally Sommers dropbear.sh@gmail.com
--- dlls/ws2_32/tests/sock.c | 141 +++++++++++++++++++++++++++++++++++++++ 1 file changed, 141 insertions(+)
diff --git a/dlls/ws2_32/tests/sock.c b/dlls/ws2_32/tests/sock.c index cddc4c125ff..6d8e7eb7a41 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> @@ -13706,6 +13707,145 @@ static void test_connect_udp(void) closesocket(client); }
+struct afunix_thread_param +{ + int sockfd; + SOCKADDR_UN addr; +}; + +static DWORD WINAPI test_afunix_client_connect_thread(void *param) +{ + struct afunix_thread_param *in = param; + ok(!connect(in->sockfd, (SOCKADDR *)&in->addr, sizeof(in->addr)), "Could not connect to Unix socket: %lu\n", + GetLastError()); + return 0; +} + +static void test_afunix(void) +{ + SOCKET listener, client, server; + SOCKADDR_UN addr = { AF_UNIX, "test_afunix.sock" }; + HANDLE clientThread; + const char serverMsg[] = "ws2_32/AF_UNIX socket test"; + char clientBuf[sizeof(serverMsg)] = { 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 ret; + + /* Test connection and send/recv */ + listener = socket(AF_UNIX, SOCK_STREAM, 0); + if (GetLastError() == WSAEAFNOSUPPORT) + win_skip("AF_UNIX sockets are unsupported, skipping...\n"); + + 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()); + + clientThread = CreateThread(NULL, 0, test_afunix_client_connect_thread, + &(struct afunix_thread_param){ client, addr }, 0, NULL); + ok(clientThread != NULL, "CreateThread failed unexpectedly: %ld\n", GetLastError()); + server = accept(listener, NULL, NULL); + ok(server != INVALID_SOCKET, "Could not accept Unix socket connection: %lu\n", + GetLastError()); + + WaitForSingleObject(clientThread, 1000); + + ret = send(server, serverMsg, sizeof(serverMsg), 0); + ok(ret == sizeof(serverMsg), "Incorrect return value from send: %d\n", ret); + ret = recv(client, clientBuf, sizeof(serverMsg), 0); + ok(ret == sizeof(serverMsg), "Incorrect return value from recv: %d\n", ret); + ok(!memcmp(serverMsg, clientBuf, sizeof(serverMsg)), "Data mismatch over Unix socket\n"); + + memset(clientBuf, 0, sizeof(clientBuf)); + + ret = sendto(server, serverMsg, sizeof(serverMsg), 0, NULL, 0); + ok(ret == sizeof(serverMsg), "Incorrect return value from sendto: %d\n", ret); + ret = recvfrom(client, clientBuf, sizeof(serverMsg), 0, NULL, 0); + ok(ret == sizeof(serverMsg), "Incorrect return value from recvfrom: %d\n", ret); + ok(!memcmp(serverMsg, clientBuf, sizeof(serverMsg)), "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 = getsockname(listener, (SOCKADDR *)&outAddr, &(int){sizeof(SOCKADDR_UN)}); + 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); + + 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; @@ -13787,6 +13927,7 @@ START_TEST( sock ) test_tcp_reset(); test_icmp(); test_connect_udp(); + test_afunix();
/* this is an io heavy test, do it at the end so the kernel doesn't start dropping packets */ test_send();