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

This commit is contained in:
Sebastian Lackner 2014-09-04 17:24:12 +02:00 committed by Alexandre Julliard
parent e65a618538
commit 652f5d9b87
1 changed files with 159 additions and 0 deletions

View File

@ -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 */