[2/2] ws2_32/tests: Add WSAPoll() tests

Bruno Jesus 00cpxxx at gmail.com
Thu May 21 13:53:01 CDT 2015


-------------- next part --------------

---
 dlls/ws2_32/tests/sock.c | 227 +++++++++++++++++++++++++++++++++++++++++++++++
 1 file changed, 227 insertions(+)

diff --git a/dlls/ws2_32/tests/sock.c b/dlls/ws2_32/tests/sock.c
index 6d328e6..585361d 100644
--- a/dlls/ws2_32/tests/sock.c
+++ b/dlls/ws2_32/tests/sock.c
@@ -71,6 +71,7 @@ static int   (WINAPI *pInetPton)(INT,LPSTR,LPVOID);
 static int   (WINAPI *pWSALookupServiceBeginW)(LPWSAQUERYSETW,DWORD,LPHANDLE);
 static int   (WINAPI *pWSALookupServiceEnd)(HANDLE);
 static int   (WINAPI *pWSALookupServiceNextW)(HANDLE,DWORD,LPDWORD,LPWSAQUERYSETW);
+static int   (WINAPI *pWSAPoll)(WSAPOLLFD *,ULONG,INT);
 
 /**************** Structs and typedefs ***************/
 
@@ -1163,6 +1164,7 @@ static void Init (void)
     pWSALookupServiceBeginW = (void *)GetProcAddress(hws2_32, "WSALookupServiceBeginW");
     pWSALookupServiceEnd = (void *)GetProcAddress(hws2_32, "WSALookupServiceEnd");
     pWSALookupServiceNextW = (void *)GetProcAddress(hws2_32, "WSALookupServiceNextW");
+    pWSAPoll = (void *)GetProcAddress(hws2_32, "WSAPoll");
 
     ok ( WSAStartup ( ver, &data ) == 0, "WSAStartup failed\n" );
     tls = TlsAlloc();
@@ -6275,6 +6277,230 @@ end:
         WSACloseEvent(ov.hEvent);
 }
 
+#define POLL_CLEAR() ix = 0
+#define POLL_SET(s, ev) {fds[ix].fd = s; fds[ix++].events = ev;}
+#define POLL_ISSET(s, rev) poll_isset(fds, ix, s, rev)
+static BOOL poll_isset(WSAPOLLFD *fds, int max, SOCKET s, int rev)
+{
+    int k;
+    for (k = 0; k < max; k++)
+    {
+        if (fds[k].fd == s && (fds[k].revents & rev) == rev)
+            return TRUE;
+    }
+    return FALSE;
+}
+
+static void test_WSAPoll(void)
+{
+    int ix, ret, err, poll_timeout;
+    SOCKET fdListen, fdRead, fdWrite;
+    struct sockaddr_in address;
+    socklen_t len;
+    static char tmp_buf[1024];
+    WSAPOLLFD fds[16];
+    select_thread_params thread_params;
+    HANDLE thread_handle;
+    DWORD id;
+
+    if (!pWSAPoll) /* >= Vista */
+    {
+        skip("WSAPoll is unsupported, some tests will be skipped.\n");
+        return;
+    }
+
+    /* Invalid parameters test */
+    SetLastError(0xdeadbeef);
+    ret = pWSAPoll(NULL, 0, 0);
+    err = GetLastError();
+    ok(ret == SOCKET_ERROR, "expected -1, got %d\n", ret);
+    ok(err == WSAEINVAL, "expected 10022, got %d\n", err);
+    SetLastError(0xdeadbeef);
+    ret = pWSAPoll(NULL, 1, 0);
+    err = GetLastError();
+    ok(ret == SOCKET_ERROR, "expected -1, got %d\n", ret);
+    ok(err == WSAEFAULT, "expected 10014, got %d\n", err);
+    SetLastError(0xdeadbeef);
+    ret = pWSAPoll(NULL, 0, 1);
+    err = GetLastError();
+    ok(ret == SOCKET_ERROR, "expected -1, got %d\n", ret);
+    ok(err == WSAEINVAL, "expected 10022, got %d\n", err);
+    SetLastError(0xdeadbeef);
+    ret = pWSAPoll(NULL, 1, 1);
+    err = GetLastError();
+    ok(ret == SOCKET_ERROR, "expected -1, got %d\n", ret);
+    ok(err == WSAEFAULT, "expected 10014, got %d\n", err);
+
+    /* WSAPoll() tries to mime the unix poll() call. The following tests do:
+     * - check if a connection attempt ended with success or error;
+     * - check if a pending connection is waiting for acceptance;
+     * - check for data to read, availability for write and OOB data
+     */
+    memset(&address, 0, sizeof(address));
+    address.sin_addr.s_addr = inet_addr("127.0.0.1");
+    address.sin_family = AF_INET;
+    len = sizeof(address);
+    fdListen = setup_server_socket(&address, &len);
+    poll_timeout = 100;
+
+    /* When no events are pending poll returns 0 with no error */
+    POLL_CLEAR();
+    POLL_SET(fdListen, POLLIN);
+    ret = pWSAPoll(fds, ix, poll_timeout);
+    ok(ret == 0, "expected 0, got %d\n", ret);
+
+    /* Test listening socket connection attempt notifications */
+    fdWrite = setup_connector_socket(&address, len, TRUE);
+    POLL_CLEAR();
+    POLL_SET(fdListen, POLLIN | POLLOUT);
+    ret = pWSAPoll(fds, ix, poll_timeout);
+    ok(ret == 1, "expected 1, got %d\n", ret);
+    ok(POLL_ISSET(fdListen, POLLRDNORM), "fdListen socket events incorrect\n");
+    len = sizeof(address);
+    fdRead = accept(fdListen, (struct sockaddr*) &address, &len);
+    ok(fdRead != INVALID_SOCKET, "expected a valid socket\n");
+
+    /* Test client side connection attempt notifications */
+    POLL_CLEAR();
+    POLL_SET(fdListen, POLLIN | POLLOUT);
+    POLL_SET(fdRead, POLLIN | POLLOUT);
+    POLL_SET(fdWrite, POLLIN | POLLOUT);
+    ret = pWSAPoll(fds, ix, poll_timeout);
+    ok(ret == 2, "expected 2, got %d\n", ret);
+    ok(POLL_ISSET(fdWrite, POLLWRNORM), "fdWrite socket events incorrect\n");
+    ok(POLL_ISSET(fdRead, POLLWRNORM), "fdRead socket events incorrect\n");
+    len = sizeof(id);
+    id = 0xdeadbeef;
+    ok(!getsockopt(fdWrite, SOL_SOCKET, SO_ERROR, (char*)&id, &len),
+       "getsockopt failed with %d\n",WSAGetLastError());
+    ok(id == 0, "expected 0, got %d\n", id);
+
+    /* Test data receiving notifications */
+    ret = send(fdWrite, "1234", 4, 0);
+    ok(ret == 4, "expected 4, got %d\n", ret);
+    POLL_CLEAR();
+    POLL_SET(fdListen, POLLIN | POLLOUT);
+    POLL_SET(fdRead, POLLIN | POLLOUT);
+    ret = pWSAPoll(fds, ix, poll_timeout);
+    ok(ret == 1, "expected 1, got %d\n", ret);
+    ok(POLL_ISSET(fdRead, POLLRDNORM) || broken(POLL_ISSET(fdRead, POLLWRNORM)) /* <= 2008 */,
+       "fdRead socket events incorrect\n");
+    ret = recv(fdRead, tmp_buf, sizeof(tmp_buf), 0);
+    ok(ret == 4, "expected 4, got %d\n", ret);
+    ok(!strcmp(tmp_buf, "1234"), "data received differs from sent\n");
+
+    /* Test OOB data notifications */
+    ret = send(fdWrite, "A", 1, MSG_OOB);
+    ok(ret == 1, "expected 1, got %d\n", ret);
+    POLL_CLEAR();
+    POLL_SET(fdListen, POLLIN | POLLOUT);
+    POLL_SET(fdRead, POLLIN);
+    ret = pWSAPoll(fds, ix, poll_timeout);
+    ok(ret == 1, "expected 1, got %d\n", ret);
+    ok(POLL_ISSET(fdRead, POLLRDBAND), "fdRead socket events incorrect\n");
+    tmp_buf[0] = 0xAF;
+    ret = recv(fdRead, tmp_buf, sizeof(tmp_buf), MSG_OOB);
+    ok(ret == 1, "expected 1, got %d\n", ret);
+    ok(tmp_buf[0] == 'A', "expected 'A', got 0x%02X\n", tmp_buf[0]);
+
+    /* If the socket is OOBINLINED the notification is like normal data */
+    ret = 1;
+    ret = setsockopt(fdRead, SOL_SOCKET, SO_OOBINLINE, (char*) &ret, sizeof(ret));
+    ok(ret == 0, "expected 0, got %d\n", ret);
+    ret = send(fdWrite, "A", 1, MSG_OOB);
+    ok(ret == 1, "expected 1, got %d\n", ret);
+    POLL_CLEAR();
+    POLL_SET(fdListen, POLLIN | POLLOUT);
+    POLL_SET(fdRead, POLLIN | POLLOUT);
+    ret = pWSAPoll(fds, ix, poll_timeout);
+    ok(ret == 1, "expected 1, got %d\n", ret);
+    tmp_buf[0] = 0xAF;
+    SetLastError(0xdeadbeef);
+    ret = recv(fdRead, tmp_buf, sizeof(tmp_buf), MSG_OOB);
+    ok(ret == SOCKET_ERROR, "expected -1, got %d", ret);
+    ok(GetLastError() == WSAEINVAL, "expected 10022, got %d\n", GetLastError());
+    ret = recv(fdRead, tmp_buf, sizeof(tmp_buf), 0);
+    ok(ret == 1, "expected 1, got %d\n", ret);
+    ok(tmp_buf[0] == 'A', "expected 'A', got 0x%02X\n", tmp_buf[0]);
+
+    /* Test connection closed notifications */
+    ret = closesocket(fdRead);
+    ok(ret == 0, "expected 0, got %d\n", ret);
+    POLL_CLEAR();
+    POLL_SET(fdListen, POLLIN | POLLOUT);
+    POLL_SET(fdWrite, POLLIN);
+    ret = pWSAPoll(fds, ix, poll_timeout);
+    ok(ret == 1, "expected 1, got %d\n", ret);
+    ok(POLL_ISSET(fdWrite, POLLHUP), "fdWrite socket events incorrect\n");
+    ret = recv(fdWrite, tmp_buf, sizeof(tmp_buf), 0);
+    ok(ret == 0, "expected 0, got %d\n", ret);
+
+    /* When a connection is attempted to a non-listening socket due to a bug
+     * in the MS code it will never be notified. This is a long standing issue
+     * that will never be fixed for compatibility reasons so we have to deal
+     * with it manually. */
+    ret = closesocket(fdWrite);
+    ok(ret == 0, "expected 0, got %d\n", ret);
+    ret = closesocket(fdListen);
+    ok(ret == 0, "expected 0, got %d\n", ret);
+    len = sizeof(address);
+    fdWrite = setup_connector_socket(&address, len, TRUE);
+    POLL_CLEAR();
+    POLL_SET(fdWrite, POLLIN | POLLOUT);
+    poll_timeout = 2000;
+    ret = pWSAPoll(fds, ix, poll_timeout);
+    ok(ret == 0, "expected 0, got %d\n", ret);
+    len = sizeof(id);
+    id = 0xdeadbeef;
+    ok(!getsockopt(fdWrite, SOL_SOCKET, SO_ERROR, (char*)&id, &len),
+       "getsockopt failed with %d\n", WSAGetLastError());
+    ok(id == WSAECONNREFUSED, "expected 10061, got %d\n", id);
+    closesocket(fdWrite);
+
+    /* Try poll() on a closed socket after connection */
+    ok(!tcp_socketpair(&fdRead, &fdWrite), "creating socket pair failed\n");
+    closesocket(fdRead);
+    POLL_CLEAR();
+    POLL_SET(fdWrite, POLLIN | POLLOUT);
+    POLL_SET(fdRead, POLLIN | POLLOUT);
+    ret = pWSAPoll(fds, ix, poll_timeout);
+    ok(ret == 1, "expected 1, got %d\n", ret);
+    ok(POLL_ISSET(fdRead, POLLNVAL), "fdRead socket events incorrect\n");
+    POLL_CLEAR();
+    POLL_SET(fdWrite, POLLIN | POLLOUT);
+    ret = pWSAPoll(fds, ix, poll_timeout);
+    ok(ret == 1, "expected 1, got %d\n", ret);
+    ok(POLL_ISSET(fdWrite, POLLWRNORM | POLLHUP) || broken(POLL_ISSET(fdWrite, POLLWRNORM)) /* <= 2008 */,
+       "fdWrite socket events incorrect\n");
+    closesocket(fdWrite);
+
+    /* Close the socket currently being polled in a thread */
+    ok(!tcp_socketpair(&fdRead, &fdWrite), "creating socket pair failed\n");
+    thread_handle = CreateThread(NULL, 0, SelectCloseThread, &fdWrite, 0, &id);
+    ok(thread_handle != NULL, "CreateThread failed unexpectedly: %d\n", GetLastError());
+    POLL_CLEAR();
+    POLL_SET(fdWrite, POLLIN | POLLOUT);
+    ret = pWSAPoll(fds, ix, poll_timeout);
+    ok(ret == 1, "expected 1, got %d\n", ret);
+    ok(POLL_ISSET(fdWrite, POLLWRNORM), "fdWrite socket events incorrect\n");
+    WaitForSingleObject (thread_handle, 1000);
+    closesocket(fdRead);
+    /* test again with less flags - behavior changes */
+    ok(!tcp_socketpair(&fdRead, &fdWrite), "creating socket pair failed\n");
+    thread_handle = CreateThread(NULL, 0, SelectCloseThread, &fdWrite, 0, &id);
+    ok(thread_handle != NULL, "CreateThread failed unexpectedly: %d\n", GetLastError());
+    POLL_CLEAR();
+    POLL_SET(fdWrite, POLLIN);
+    ret = pWSAPoll(fds, ix, poll_timeout);
+    ok(ret == 1, "expected 1, got %d\n", ret);
+    ok(POLL_ISSET(fdWrite, POLLNVAL), "fdWrite socket events incorrect\n");
+    WaitForSingleObject (thread_handle, 1000);
+    closesocket(fdRead);
+}
+#undef POLL_SET
+#undef POLL_ISSET
+#undef POLL_CLEAR
+
 static void test_GetAddrInfoW(void)
 {
     static const WCHAR port[] = {'8','0',0};
@@ -8682,6 +8908,7 @@ START_TEST( sock )
     test_WSASendMsg();
     test_WSASendTo();
     test_WSARecv();
+    test_WSAPoll();
 
     test_events(0);
     test_events(1);
-- 
2.1.4



More information about the wine-patches mailing list