[PATCH 1/4] kernel32/tests: Add tests for named pipes in PIPE_NOWAIT mode.

Brendan Shanks bshanks at codeweavers.com
Tue Oct 1 11:16:57 CDT 2019


Signed-off-by: Brendan Shanks <bshanks at codeweavers.com>
---
 dlls/kernel32/tests/pipe.c | 108 +++++++++++++++++++++++++++++++++++++
 1 file changed, 108 insertions(+)

diff --git a/dlls/kernel32/tests/pipe.c b/dlls/kernel32/tests/pipe.c
index f61d441303..227575ece3 100644
--- a/dlls/kernel32/tests/pipe.c
+++ b/dlls/kernel32/tests/pipe.c
@@ -3887,6 +3887,113 @@ static void test_wait_pipe(void)
     CloseHandle(ov.hEvent);
 }
 
+static DWORD CALLBACK test_nowait_read_thread(LPVOID arg)
+{
+    HANDLE *pipewrite = arg;
+    static const char buf[] = "bits";
+    DWORD written;
+
+    Sleep(2000);
+    WriteFile(*pipewrite, buf, sizeof(buf), &written, NULL);
+    return 0;
+}
+static DWORD CALLBACK test_nowait_write_thread(LPVOID arg)
+{
+    HANDLE *piperead = arg;
+    char buf[32768];
+    DWORD read;
+
+    Sleep(2000);
+    ReadFile(*piperead, buf, sizeof(buf), &read, NULL);
+    return 0;
+}
+static DWORD CALLBACK test_nowait_connect_thread(LPVOID arg)
+{
+    HANDLE hFile;
+
+    Sleep(2000);
+    hFile = CreateFileA(PIPENAME, GENERIC_READ | GENERIC_WRITE, 0, NULL, OPEN_EXISTING, 0, 0);
+    ok(hFile != INVALID_HANDLE_VALUE, "CreateFileA failed\n");
+    ok(CloseHandle(hFile), "CloseHandle failed\n");
+    return 0;
+}
+static void test_nowait(void)
+{
+    SECURITY_ATTRIBUTES pipe_attr;
+    HANDLE piperead, pipewrite, hThread;
+    DWORD mode;
+    DWORD read, write;
+    char readbuf[32768];
+
+    pipe_attr.nLength = sizeof(SECURITY_ATTRIBUTES);
+    pipe_attr.bInheritHandle = TRUE;
+    pipe_attr.lpSecurityDescriptor = NULL;
+
+    /* CreatePipe, use SetNamedHandleState to enable PIPE_NOWAIT, and read from empty pipe */
+    ok(CreatePipe(&piperead, &pipewrite, &pipe_attr, 0) != 0, "CreatePipe failed\n");
+    mode = PIPE_NOWAIT;
+    ok(SetNamedPipeHandleState(piperead, &mode, NULL, NULL) != 0, "SetNamedPipeHandleState failed\n");
+    /* spawn a thread that writes to the pipe after 2 seconds so the test won't hang if ReadFile blocks */
+    hThread = CreateThread(NULL, 0, test_nowait_read_thread, &pipewrite, 0, NULL);
+    ok(hThread != NULL, "CreateThread failed. %d\n", GetLastError());
+    SetLastError(0xdeadbeef);
+    todo_wine ok(ReadFile(piperead,readbuf,sizeof(readbuf),&read, NULL) == FALSE, "ReadFile should fail\n");
+    todo_wine ok(GetLastError() == ERROR_NO_DATA, "got %d should be ERROR_NO_DATA\n", GetLastError());
+    ok(WaitForSingleObject(hThread,INFINITE) == WAIT_OBJECT_0, "WaitForSingleObject\n");
+    ok(CloseHandle(hThread), "CloseHandle for the thread failed\n");
+    ok(CloseHandle(pipewrite), "CloseHandle for the write pipe failed\n");
+    ok(CloseHandle(piperead), "CloseHandle for the read pipe failed\n");
+
+    /* CreatePipe, use SetNamedHandleState to enable PIPE_NOWAIT, and write to full pipe */
+    ok(CreatePipe(&piperead, &pipewrite, &pipe_attr, 512) != 0, "CreatePipe failed\n");
+    mode = PIPE_NOWAIT;
+    ok(SetNamedPipeHandleState(pipewrite, &mode, NULL, NULL) != 0, "SetNamedPipeHandleState failed\n");
+    /* spawn a thread that reads from the pipe after 2 seconds so the test won't hang if WriteFile blocks */
+    hThread = CreateThread(NULL, 0, test_nowait_write_thread, &piperead, 0, NULL);
+    ok(hThread != NULL, "CreateThread failed. %d\n", GetLastError());
+    SetLastError(0xdeadbeef);
+    ok(WriteFile(pipewrite,readbuf,sizeof(readbuf),&write, NULL) == TRUE, "WriteFile should return true\n");
+    /* WriteFile only documents that 'write < sizeof(readbuf)' for this case, but Windows
+     * doesn't seem to do partial writes ('write == 0' always)
+     */
+    todo_wine ok(write < sizeof(readbuf), "WriteFile should fail to write the whole buffer\n");
+    todo_wine ok(write == 0, "WriteFile shouldn't do partial writes\n");
+    ok(CloseHandle(hThread), "CloseHandle for the thread failed\n");
+    ok(CloseHandle(pipewrite), "CloseHandle for the write pipe failed\n");
+    ok(CloseHandle(piperead), "CloseHandle for the read pipe failed\n");
+
+    /* CreateNamedPipe with PIPE_NOWAIT, test ConnectNamedPipe */
+    pipewrite = CreateNamedPipeA(PIPENAME, PIPE_ACCESS_DUPLEX, PIPE_TYPE_BYTE | PIPE_NOWAIT,
+        /* nMaxInstances */ 1,
+        /* nOutBufSize */ 512,
+        /* nInBufSize */ 512,
+        /* nDefaultWait */ NMPWAIT_USE_DEFAULT_WAIT,
+        /* lpSecurityAttrib */ NULL);
+    ok(pipewrite != INVALID_HANDLE_VALUE, "CreateNamedPipe failed\n");
+    /* spawn a thread that connects to the pipe after 2 seconds so the test won't hang if ConnectNamedPipe blocks */
+    hThread = CreateThread(NULL, 0, test_nowait_connect_thread, NULL, 0, NULL);
+    ok(hThread != NULL, "CreateThread failed. %d\n", GetLastError());
+    SetLastError(0xdeadbeef);
+    todo_wine ok(ConnectNamedPipe(pipewrite,NULL) == FALSE, "ConnectNamedPipe should fail\n");
+    todo_wine ok(GetLastError() == ERROR_PIPE_LISTENING, "got %d should be ERROR_PIPE_LISTENING\n", GetLastError());
+    /* wait for thread to finish (connects and disconnects), then test ConnectNamedPipe again */
+    ok(WaitForSingleObject(hThread,INFINITE) == WAIT_OBJECT_0, "WaitForSingleObject\n");
+    ok(CloseHandle(hThread), "CloseHandle for the thread failed\n");
+    SetLastError(0xdeadbeef);
+    todo_wine ok(ConnectNamedPipe(pipewrite,NULL) == FALSE, "ConnectNamedPipe should fail\n");
+    todo_wine ok(GetLastError() == ERROR_NO_DATA, "got %d should be ERROR_NO_DATA\n", GetLastError());
+    /* call DisconnectNamedPipe and test ConnectNamedPipe again */
+    ok(DisconnectNamedPipe(pipewrite) == TRUE, "DisconnectNamedPipe should succeed\n");
+    hThread = CreateThread(NULL, 0, test_nowait_connect_thread, NULL, 0, NULL);
+    ok(hThread != NULL, "CreateThread failed. %d\n", GetLastError());
+    SetLastError(0xdeadbeef);
+    todo_wine ok(ConnectNamedPipe(pipewrite,NULL) == FALSE, "ConnectNamedPipe should fail\n");
+    todo_wine ok(GetLastError() == ERROR_PIPE_LISTENING, "got %d should be ERROR_PIPE_LISTENING\n", GetLastError());
+    ok(WaitForSingleObject(hThread,INFINITE) == WAIT_OBJECT_0, "WaitForSingleObject\n");
+    ok(CloseHandle(hThread), "CloseHandle for the thread failed\n");
+    ok(CloseHandle(pipewrite), "CloseHandle for the write pipe failed\n");
+}
+
 START_TEST(pipe)
 {
     char **argv;
@@ -3954,4 +4061,5 @@ START_TEST(pipe)
     test_namedpipe_session_id();
     test_multiple_instances();
     test_wait_pipe();
+    test_nowait();
 }
-- 
2.17.1




More information about the wine-devel mailing list