Sebastian Lackner : kernel32/tests: Add additional tests for multithreaded partial reads from named pipes.

Alexandre Julliard julliard at wine.codeweavers.com
Thu Sep 4 14:48:40 CDT 2014


Module: wine
Branch: master
Commit: 652f5d9b8715fb71b15cfb93fa741474ac3b757d
URL:    http://source.winehq.org/git/wine.git/?a=commit;h=652f5d9b8715fb71b15cfb93fa741474ac3b757d

Author: Sebastian Lackner <sebastian at fds-team.de>
Date:   Thu Sep  4 17:24:12 2014 +0200

kernel32/tests: Add additional tests for multithreaded partial reads from named pipes.

---

 dlls/kernel32/tests/pipe.c | 159 +++++++++++++++++++++++++++++++++++++++++++++
 1 file changed, 159 insertions(+)

diff --git a/dlls/kernel32/tests/pipe.c b/dlls/kernel32/tests/pipe.c
index eeeaa32..3f89086 100644
--- a/dlls/kernel32/tests/pipe.c
+++ b/dlls/kernel32/tests/pipe.c
@@ -43,6 +43,72 @@ static void CALLBACK user_apc(ULONG_PTR param)
     user_apc_ran = TRUE;
 }
 
+
+enum rpcThreadOp
+{
+    RPC_READFILE
+};
+
+struct rpcThreadArgs
+{
+    ULONG_PTR returnValue;
+    DWORD lastError;
+    enum rpcThreadOp op;
+    ULONG_PTR args[5];
+};
+
+static DWORD CALLBACK rpcThreadMain(LPVOID arg)
+{
+    struct rpcThreadArgs *rpcargs = (struct rpcThreadArgs *)arg;
+    trace("rpcThreadMain starting\n");
+    SetLastError( rpcargs->lastError );
+
+    switch (rpcargs->op)
+    {
+        case RPC_READFILE:
+            rpcargs->returnValue = (ULONG_PTR)ReadFile( (HANDLE)rpcargs->args[0],         /* hFile */
+                                                        (LPVOID)rpcargs->args[1],         /* buffer */
+                                                        (DWORD)rpcargs->args[2],          /* bytesToRead */
+                                                        (LPDWORD)rpcargs->args[3],        /* bytesRead */
+                                                        (LPOVERLAPPED)rpcargs->args[4] ); /* overlapped */
+            break;
+
+        default:
+            SetLastError( ERROR_CALL_NOT_IMPLEMENTED );
+            rpcargs->returnValue = 0;
+            break;
+    }
+
+    rpcargs->lastError = GetLastError();
+    trace("rpcThreadMain returning\n");
+    return 0;
+}
+
+/* Runs ReadFile(...) from a different thread */
+static BOOL RpcReadFile(HANDLE hFile, LPVOID buffer, DWORD bytesToRead, LPDWORD bytesRead, LPOVERLAPPED overlapped)
+{
+    struct rpcThreadArgs rpcargs;
+    HANDLE thread;
+    DWORD threadId;
+
+    rpcargs.returnValue = 0;
+    rpcargs.lastError = GetLastError();
+    rpcargs.op = RPC_READFILE;
+    rpcargs.args[0] = (ULONG_PTR)hFile;
+    rpcargs.args[1] = (ULONG_PTR)buffer;
+    rpcargs.args[2] = (ULONG_PTR)bytesToRead;
+    rpcargs.args[3] = (ULONG_PTR)bytesRead;
+    rpcargs.args[4] = (ULONG_PTR)overlapped;
+
+    thread = CreateThread(NULL, 0, rpcThreadMain, (void *)&rpcargs, 0, &threadId);
+    ok(thread != NULL, "CreateThread failed. %d\n", GetLastError());
+    ok(WaitForSingleObject(thread, INFINITE) == WAIT_OBJECT_0, "WaitForSingleObject failed with %d.\n", GetLastError());
+    CloseHandle(thread);
+
+    SetLastError(rpcargs.lastError);
+    return (BOOL)rpcargs.returnValue;
+}
+
 static void test_CreateNamedPipe(int pipemode)
 {
     HANDLE hnp;
@@ -372,6 +438,99 @@ static void test_CreateNamedPipe(int pipemode)
             ok(readden == sizeof(obuf) - 4, "read got %d bytes 8\n", readden);
             ok(memcmp(obuf, ibuf, written) == 0, "content check 8\n");
 
+            /* The following test shows that when doing a partial read of a message, the rest
+             * is still in the pipe, and can be received from a second thread. This shows
+             * especially that the content is _not_ stored in thread-local-storage until it is
+             * completely transmitted. The same method works even across multiple processes. */
+            memset(ibuf, 0, sizeof(ibuf));
+            ok(WriteFile(hnp, obuf, sizeof(obuf), &written, NULL), "WriteFile 9\n");
+            ok(written == sizeof(obuf), "write file len 9\n");
+            ok(WriteFile(hnp, obuf2, sizeof(obuf2), &written, NULL), "WriteFile 9\n");
+            ok(written == sizeof(obuf2), "write file len 9\n");
+            SetLastError(0xdeadbeef);
+            todo_wine
+            ok(!ReadFile(hFile, ibuf, 4, &readden, NULL), "ReadFile 9\n");
+            todo_wine
+            ok(GetLastError() == ERROR_MORE_DATA, "wrong error 9\n");
+            ok(readden == 4, "read got %d bytes 9\n", readden);
+            SetLastError(0xdeadbeef);
+            ret = RpcReadFile(hFile, ibuf + 4, 4, &readden, NULL);
+            todo_wine
+            ok(!ret, "RpcReadFile 9\n");
+            todo_wine
+            ok(GetLastError() == ERROR_MORE_DATA, "wrong error 9\n");
+            ok(readden == 4, "read got %d bytes 9\n", readden);
+            ret = RpcReadFile(hFile, ibuf + 8, sizeof(ibuf), &readden, NULL);
+            ok(ret, "RpcReadFile 9\n");
+            todo_wine
+            ok(readden == sizeof(obuf) - 8, "read got %d bytes 9\n", readden);
+            ok(memcmp(obuf, ibuf, sizeof(obuf)) == 0, "content check 9\n");
+            if (readden <= sizeof(obuf) - 8) /* blocks forever if second part was already received */
+            {
+                memset(ibuf, 0, sizeof(ibuf));
+                SetLastError(0xdeadbeef);
+                ret = RpcReadFile(hFile, ibuf, 4, &readden, NULL);
+                ok(!ret, "RpcReadFile 9\n");
+                todo_wine
+                ok(GetLastError() == ERROR_MORE_DATA, "wrong error 9\n");
+                ok(readden == 4, "read got %d bytes 9\n", readden);
+                SetLastError(0xdeadbeef);
+                todo_wine
+                ok(!ReadFile(hFile, ibuf + 4, 4, &readden, NULL), "ReadFile 9\n");
+                todo_wine
+                ok(GetLastError() == ERROR_MORE_DATA, "wrong error 9\n");
+                ok(readden == 4, "read got %d bytes 9\n", readden);
+                ret = RpcReadFile(hFile, ibuf + 8, sizeof(ibuf), &readden, NULL);
+                ok(ret, "RpcReadFile 9\n");
+                ok(readden == sizeof(obuf2) - 8, "read got %d bytes 9\n", readden);
+                ok(memcmp(obuf2, ibuf, sizeof(obuf2)) == 0, "content check 9\n");
+            }
+
+            /* Now the reverse direction */
+            memset(ibuf, 0, sizeof(ibuf));
+            ok(WriteFile(hFile, obuf2, sizeof(obuf2), &written, NULL), "WriteFile 10\n");
+            ok(written == sizeof(obuf2), "write file len 10\n");
+            ok(WriteFile(hFile, obuf, sizeof(obuf), &written, NULL), "WriteFile 10\n");
+            ok(written == sizeof(obuf), "write file len 10\n");
+            SetLastError(0xdeadbeef);
+            todo_wine
+            ok(!ReadFile(hnp, ibuf, 4, &readden, NULL), "ReadFile 10\n");
+            todo_wine
+            ok(GetLastError() == ERROR_MORE_DATA, "wrong error 10\n");
+            ok(readden == 4, "read got %d bytes 10\n", readden);
+            SetLastError(0xdeadbeef);
+            ret = RpcReadFile(hnp, ibuf + 4, 4, &readden, NULL);
+            todo_wine
+            ok(!ret, "RpcReadFile 10\n");
+            todo_wine
+            ok(GetLastError() == ERROR_MORE_DATA, "wrong error 10\n");
+            ok(readden == 4, "read got %d bytes 10\n", readden);
+            ret = RpcReadFile(hnp, ibuf + 8, sizeof(ibuf), &readden, NULL);
+            ok(ret, "RpcReadFile 10\n");
+            todo_wine
+            ok(readden == sizeof(obuf2) - 8, "read got %d bytes 10\n", readden);
+            ok(memcmp(obuf2, ibuf, sizeof(obuf2)) == 0, "content check 10\n");
+            if (readden <= sizeof(obuf2) - 8) /* blocks forever if second part was already received */
+            {
+                memset(ibuf, 0, sizeof(ibuf));
+                SetLastError(0xdeadbeef);
+                ret = RpcReadFile(hnp, ibuf, 4, &readden, NULL);
+                ok(!ret, "RpcReadFile 10\n");
+                todo_wine
+                ok(GetLastError() == ERROR_MORE_DATA, "wrong error 10\n");
+                ok(readden == 4, "read got %d bytes 10\n", readden);
+                SetLastError(0xdeadbeef);
+                todo_wine
+                ok(!ReadFile(hnp, ibuf + 4, 4, &readden, NULL), "ReadFile 10\n");
+                todo_wine
+                ok(GetLastError() == ERROR_MORE_DATA, "wrong error 10\n");
+                ok(readden == 4, "read got %d bytes 10\n", readden);
+                ret = RpcReadFile(hnp, ibuf + 8, sizeof(ibuf), &readden, NULL);
+                ok(ret, "RpcReadFile 10\n");
+                ok(readden == sizeof(obuf) - 8, "read got %d bytes 10\n", readden);
+                ok(memcmp(obuf, ibuf, sizeof(obuf)) == 0, "content check 10\n");
+            }
+
         }
 
         /* Picky conformance tests */




More information about the wine-cvs mailing list