Pipe tests coprrected

Uwe Bonnes bon at elektron.ikp.physik.tu-darmstadt.de
Tue Feb 24 12:01:11 CST 2004


Changelog:
	dlls/kernel/tests/pipe.c
	Added tests for redirected STDIN/STDOUT
	Added todo_wine test for waiting on closed pipe

The tests now succeed on NT40(vmware)	

-- 
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 -w -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	24 Feb 2004 17:58:47 -0000
@@ -48,8 +48,95 @@
 #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
+ *
+ * DON'T use ok() or printf() here, as stdhandles may be redirected
+ *
+ */
+static void doChild(const char* action, const char* handlename, const char* argument)
+{
+    CHAR buf[BUFSIZE];
+    DWORD dwRead, dwWritten; 
+    HANDLE hStdin, hStdout, hTest; 
+    BOOL fSuccess; 
+ 
+    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)) 
+	    return; 
+	
+	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,16 +673,165 @@
     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)
 {
-    trace("test 1 of 4:\n");
+   int b = init();
+    ok(b, "Basic init of CreateProcess test\n");
+    if (!b) return;
+    if (myARGC >2)
+    {
+	doChild(myARGV[2],(myARGV[3])?myARGV[3]:"",(myARGV[4])?myARGV[4]:"");
+    }
+    else
+      {
+	trace("test 1 of 7:\n");
     test_DisconnectNamedPipe();
-    trace("test 2 of 4:\n");
+	trace("test 2 of 7:\n");
     test_CreateNamedPipe_instances_must_match();
-    trace("test 3 of 4:\n");
+	trace("test 3 of 7:\n");
     test_NamedPipe_2();
-    trace("test 4 of 4:\n");
+	trace("test 4 of 7:\n");
     test_CreateNamedPipe();
+	trace("test 5 of 7:\n");
+	test_CreatePipe(); 
+	trace("test 6 of 7:\n");
+	test_WaitPipe(); 
     trace("all tests done\n");
+      }
 }



More information about the wine-patches mailing list