Test Cases for CreatePipe
Uwe Bonnes
bon at elektron.ikp.physik.tu-darmstadt.de
Sun Feb 22 09:12:28 CST 2004
Changelog:
dlls/kernel/test/pipe.c:
Test connecting Standard handle of processes
Test for detecting a broken pipe (Still todo_wine)
--
Uwe Bonnes bon at elektron.ikp.physik.tu-darmstadt.de
Institut fuer Kernphysik Schlossgartenstrasse 9 64289 Darmstadt
--------- Tel. 06151 162516 -------- Fax. 06151 164321 ----------
Index: wine/dlls/kernel/tests/pipe.c
===================================================================
RCS file: /home/wine/wine/dlls/kernel/tests/pipe.c,v
retrieving revision 1.9
diff -u -r1.9 pipe.c
--- wine/dlls/kernel/tests/pipe.c 6 Feb 2004 05:24:34 -0000 1.9
+++ wine/dlls/kernel/tests/pipe.c 22 Feb 2004 14:53:55 -0000
@@ -48,8 +48,93 @@
#include <wtypes.h>
#include <winerror.h>
+static int myARGC;
+static char** myARGV;
+static char selfname[MAX_PATH];
+#define BUFSIZE 0x1000
+
#define PIPENAME "\\\\.\\PiPe\\tests_" __FILE__
+/******************************************************************
+ * init
+ *
+ * generates basic information like:
+ * base: absolute path to curr dir
+ * selfname: the way to reinvoke ourselves
+ */
+static int init(void)
+{
+ myARGC = winetest_get_mainargs( &myARGV );
+ strcpy(selfname, myARGV[0]);
+ return 1;
+}
+
+/******************************************************************
+ * doChild
+ *
+ * helper process for pipes
+ * - either copy stdin to stdout
+ * - or close the indicated handle and simple return
+ */
+static void doChild(const char* action, const char* handlename, const char* argument)
+{
+ CHAR buf[BUFSIZE];
+ DWORD dwRead, dwWritten;
+ HANDLE hStdin, hStdout, hTest;
+ BOOL fSuccess;
+
+ printf("BON: action %s handlename %s arg %s\n", action, handlename,argument);
+ if(!action)
+ return;
+ if (!lstrcmpiA(action,"redirect"))
+ {
+ hStdout = GetStdHandle(STD_OUTPUT_HANDLE);
+ hStdin = GetStdHandle(STD_INPUT_HANDLE);
+ if ((hStdout == INVALID_HANDLE_VALUE) ||
+ (hStdin == INVALID_HANDLE_VALUE))
+ ExitProcess(1);
+
+ for (;;)
+ {
+ // Read from standard input.
+ fSuccess = ReadFile(hStdin, buf, BUFSIZE, &dwRead, NULL);
+ if (! fSuccess || dwRead == 0)
+ break;
+
+ // Write to standard output.
+ fSuccess = WriteFile(hStdout, buf, dwRead, &dwWritten, NULL);
+ if (! fSuccess)
+ break;
+ }
+ }
+ else if (!(lstrcmpiA(action,"close")))
+ {
+ if (!handlename)
+ return;
+ if(!lstrcmpiA(handlename,"STD_OUTPUT_HANDLE"))
+ hTest = GetStdHandle(STD_OUTPUT_HANDLE);
+ else if(!lstrcmpiA(handlename,"STD_ERROR_HANDLE"))
+ hTest = GetStdHandle(STD_ERROR_HANDLE);
+ else if(!lstrcmpiA(handlename,"STD_INPUT_HANDLE"))
+ hTest = GetStdHandle(STD_INPUT_HANDLE);
+ else
+ return;
+ if ((hTest == INVALID_HANDLE_VALUE))
+ return;
+ /* if the tested handle is an output handle, write the command argument to it */
+ if((!lstrcmpiA(handlename,"STD_OUTPUT_HANDLE") || (!lstrcmpiA(handlename,"STD_ERROR_HANDLE")))&&
+ (argument))
+ {
+ dwRead =strlen(argument)+ 1;
+ WriteFile(hTest, argument, dwRead, &dwWritten, NULL);
+ ok (dwRead == dwWritten , "Unexpected Resulte when writing to Handle\n");
+ }
+ CloseHandle(hTest);
+ }
+ return;
+}
+
+
void test_CreateNamedPipe(void)
{
HANDLE hnp;
@@ -586,9 +671,152 @@
ok(CloseHandle(hnp), "CloseHandle\n");
}
+void test_CreatePipe(void)
+{
+ /* Adapted from the MSDN SDK example
+ * "Creating a Child Process with Redirected Input and Output"
+ */
+
+ HANDLE hChildStdinRd, hChildStdinWr, hChildStdinWrDup,
+ hChildStdoutRd, hChildStdoutWr, hChildStdoutRdDup,
+ hSaveStdin, hSaveStdout;
+ SECURITY_ATTRIBUTES saAttr;
+ PROCESS_INFORMATION piProcInfo;
+ STARTUPINFO siStartInfo;
+ char buffer[BUFSIZE];
+ char resbuf[BUFSIZE];
+ DWORD dwWritten, dwRead;
+
+ /* Set the bInheritHandle flag so pipe handles are inherited. */
+
+ saAttr.nLength = sizeof(SECURITY_ATTRIBUTES);
+ saAttr.bInheritHandle = TRUE;
+ saAttr.lpSecurityDescriptor = NULL;
+
+ /* Pipe for STDOUT of child */
+ hSaveStdout = GetStdHandle(STD_OUTPUT_HANDLE);
+ ok(CreatePipe(&hChildStdoutRd, &hChildStdoutWr, &saAttr, 0) != 0, "Stdout pipe creation failed\n");
+ ok(SetStdHandle(STD_OUTPUT_HANDLE, hChildStdoutWr) != 0, "Redirecting STDOUT failed");
+ ok(DuplicateHandle(GetCurrentProcess(), hChildStdoutRd,
+ GetCurrentProcess(), &hChildStdoutRdDup , 0,
+ FALSE,DUPLICATE_SAME_ACCESS) != 0,"DuplicateHandle failed");
+ CloseHandle(hChildStdoutRd);
+
+ /* Pipe for STDIN of child */
+
+ hSaveStdin = GetStdHandle(STD_INPUT_HANDLE);
+ ok (CreatePipe(&hChildStdinRd, &hChildStdinWr, &saAttr, 0) !=0, "DuplicateHandle failed");
+ ok ( SetStdHandle(STD_INPUT_HANDLE, hChildStdinRd)!= 0, "Redirecting Stdin failed");
+
+ /*Duplicate the write handle to the pipe so it is not inherited */
+
+ ok (DuplicateHandle(GetCurrentProcess(), hChildStdinWr,
+ GetCurrentProcess(), &hChildStdinWrDup, 0,
+ FALSE, // not inherited
+ DUPLICATE_SAME_ACCESS) !=0,"DuplicateHandle failed");
+
+ CloseHandle(hChildStdinWr);
+
+ ZeroMemory( &piProcInfo, sizeof(PROCESS_INFORMATION) );
+ ZeroMemory( &siStartInfo, sizeof(STARTUPINFO) );
+ siStartInfo.cb = sizeof(STARTUPINFO);
+ sprintf(buffer, "%s tests/pipe.c redirect",selfname);
+ ok (CreateProcess(NULL,
+ buffer, // command line
+ NULL, // process security attributes
+ NULL, // primary thread security attributes
+ TRUE, // handles are inherited
+ 0, // creation flags
+ NULL, // use parent's environment
+ NULL, // use parent's current directory
+ &siStartInfo, // STARTUPINFO pointer
+ &piProcInfo // receives PROCESS_INFORMATION
+ ) != 0, "CreateProcess failed\n");
+ CloseHandle(piProcInfo.hProcess);
+ CloseHandle(piProcInfo.hThread);
+ /* Restore sthe saved stdadrd handles */
+ ok ( SetStdHandle(STD_INPUT_HANDLE, hSaveStdin) != 0,"Re-redirecting Stdin failed\n");
+ ok ( SetStdHandle(STD_OUTPUT_HANDLE, hSaveStdout) != 0, "Re-redirecting Stdout failed\n");
+
+ /* some data to transfer */
+ sprintf(buffer, "Some senseless data");
+ WriteFile(hChildStdinWrDup, buffer, strlen(buffer) +1, &dwWritten, NULL);
+ ok (strlen(buffer) +1 == dwWritten," Pipe write error ");
+ /* Close the pipe handle so the child process stops reading */
+ ok ( CloseHandle(hChildStdinWrDup) != 0 ,"Close outbound pipe failed\n");
+
+ /* Close the write end of the pipe before reading from the
+ read end of the pipe */
+
+ ok (CloseHandle(hChildStdoutWr) != 0, "Closing handle failed");
+ ok (ReadFile( hChildStdoutRdDup, resbuf, BUFSIZE, &dwRead, NULL) != 0, "Read pipe failed\n");
+ ok ( dwRead == dwWritten,"Unexpected length of pipe read\n");
+}
+void test_WaitPipe(void)
+{
+ /* Mimic the way Altera Quartus waits on the jtagserver process
+ * http://www.winehq.org/hypermail/wine-devel/2003/01/0486.html
+ */
+
+ HANDLE hRd, hRdDup, hWr;
+ SECURITY_ATTRIBUTES saAttr;
+ PROCESS_INFORMATION piProcInfo;
+ STARTUPINFO siStartInfo;
+ CHAR buf[BUFSIZE], teststring[]="Some more senseless data";
+ DWORD dwRead;
+
+ /* Set the bInheritHandle flag so pipe handles are inherited. */
+
+ saAttr.nLength = sizeof(SECURITY_ATTRIBUTES);
+ saAttr.bInheritHandle = TRUE;
+ saAttr.lpSecurityDescriptor = NULL;
+
+ ok(CreatePipe(&hRd, &hWr, &saAttr, 0) != 0, "CreatePipe failed\n");
+ ok(DuplicateHandle(GetCurrentProcess(), hRd,
+ GetCurrentProcess(), &hRdDup , 0,
+ FALSE,DUPLICATE_SAME_ACCESS) != 0,"DuplicateHandle failed");
+ CloseHandle(hRd);
+
+
+ ZeroMemory( &piProcInfo, sizeof(PROCESS_INFORMATION) );
+ ZeroMemory( &siStartInfo, sizeof(STARTUPINFO) );
+ siStartInfo.cb = sizeof(STARTUPINFO);
+ siStartInfo.dwFlags=STARTF_USESTDHANDLES;
+ siStartInfo.hStdError=hWr;
+ sprintf(buf, "%s tests/pipe.c close STD_ERROR_HANDLE \"%s\"",selfname,teststring);
+ ok (CreateProcess(NULL,
+ buf, // command line
+ NULL, // process security attributes
+ NULL, // primary thread security attributes
+ TRUE, // handles are inherited
+ 0, // creation flags
+ NULL, // use parent's environment
+ NULL, // use parent's current directory
+ &siStartInfo, // STARTUPINFO pointer
+ &piProcInfo // receives PROCESS_INFORMATION
+ ) != 0, "CreateProcess failed\n");
+ CloseHandle(hWr);
+ ok(WaitForSingleObject(piProcInfo.hProcess, 30000) == WAIT_OBJECT_0, "Child process termination\n");
+ CloseHandle(piProcInfo.hProcess);
+ CloseHandle(piProcInfo.hThread);
+
+ /* Not sure what happend with pending data when the write end is closes */
+ ok(ReadFile(hRdDup, buf, BUFSIZE, &dwRead, NULL)!=0,"Reading from broken pipe with pending data failed\n");
+ ok(lstrcmpA(buf,teststring) == 0, "Unexpected data from pipe\n");
+ todo_wine ok(ReadFile(hRdDup, buf, BUFSIZE, &dwRead, NULL)==0,"Empty Broken pipe not detected\n");
+ todo_wine ok(GetLastError() == ERROR_BROKEN_PIPE , "unexpected error code: %ld\n", GetLastError());
+}
START_TEST(pipe)
{
+ int b = init();
+ ok(b, "Basic init of CreateProcess test\n");
+ if (!b) return;
+ if (myARGC >2)
+ {
+ doChild(myARGV[2],(myARGV[3])?myARGV[3]:0,(myARGV[4])?myARGV[4]:0);
+ return;
+ }
trace("test 1 of 4:\n");
test_DisconnectNamedPipe();
trace("test 2 of 4:\n");
@@ -597,5 +825,7 @@
test_NamedPipe_2();
trace("test 4 of 4:\n");
test_CreateNamedPipe();
+ test_CreatePipe();
+ test_WaitPipe();
trace("all tests done\n");
}
More information about the wine-patches
mailing list