(file) Return to wsock32_main.c CVS log (file) (dir) Up to [RizwankCVS] / wine4 / wine / dlls / wsock32 / tests

Diff for /wine4/wine/dlls/wsock32/tests/wsock32_main.c between version 1.1 and 1.12

version 1.1, 2005/02/04 03:01:30 version 1.12, 2005/02/22 05:15:01
Line 1 
Line 1 
 /* /*
  * Unit tests for named pipe functions in Wine   * Unit tests for 32-bit socket functions in Wine
  *  *
  * Copyright (c) 2002 Dan Kegel   * Copyright (c) 2005 Thomas Kho, Fredy Garcia, Douglas Rosenberg
  *  *
  * This library is free software; you can redistribute it and/or  * This library is free software; you can redistribute it and/or
  * modify it under the terms of the GNU Lesser General Public  * modify it under the terms of the GNU Lesser General Public
Line 18 
Line 18 
  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
  */  */
  
 #include <assert.h>  
 #include <stdarg.h>  
 #include <stdlib.h>  
 #include <stdio.h> #include <stdio.h>
 #include <time.h>  
  
 #include <windef.h>  #include <windows.h>
 #include <winbase.h>  
 #include <winsock.h> #include <winsock.h>
   #include <wtypes.h>
   #include <winerror.h>
   #include <string.h>
  
 #ifndef STANDALONE #ifndef STANDALONE
 #include "wine/test.h" #include "wine/test.h"
Line 45 
Line 43 
 #define todo_wine #define todo_wine
 #endif #endif
  
 #include <wtypes.h>  #define NUM_CLIENTS 1
 #include <winerror.h>  // amount of data to transfer from each client to server
   #define TRANSFER_SIZE 1000000
  
 #define PIPENAME "\\\\.\\PiPe\\tests_pipe.c"  int clientsDone = 0;
   int sizeofSOCKADDR_IN = sizeof(SOCKADDR_IN);
  
 #define NB_SERVER_LOOPS 8  struct TestParams {
           int serverSock;
           int serverType;
           int serverPort;
           int clientPort[NUM_CLIENTS];
   };
  
 static HANDLE alarm_event;  struct ClientParams {
           struct TestParams *test;
           int clientNum; // 1...NUM_CLIENTS
   };
  
 static void test_CreateNamedPipe(int pipemode)  struct ServerThread {
           HANDLE* ServerThread;
           DWORD* ServerThreadID;
           SOCKET Socket; // socket to communicate with client
           SOCKADDR_IN Client; // client info
   };
   
   static void test_Startup(void);
   void BlockingClient(int *serverPort);
   void BlockingServer(int *port);
   static void test_ClientServerBlocking_1(void);
   static void test_Startup(void);
   
   // StartNetworkApp creates socket sock of type type and returns assigned port number in addr.
   void StartNetworkApp(int type, SOCKET *sock, SOCKADDR_IN *addr)
 { {
     HANDLE hnp;          SOCKADDR_IN tmpAddr;
     HANDLE hFile;          int tmpAddrSize;
     static const char obuf[] = "Bit Bucket";  
     static const char obuf2[] = "More bits";          *sock = socket(AF_INET, type, 0);
     char ibuf[32], *pbuf;          if (*sock == INVALID_SOCKET) {
     DWORD written;                  ok( 0 , "Error in socket()");
     DWORD readden;                  WSACleanup();
     DWORD avail;                  exit(0);
     DWORD lpmode;  
   
     if (pipemode == PIPE_TYPE_BYTE)  
         trace("test_CreateNamedPipe starting in byte mode\n");  
     else  
         trace("test_CreateNamedPipe starting in message mode\n");  
     /* Bad parameter checks */  
     hnp = CreateNamedPipe("not a named pipe", PIPE_ACCESS_DUPLEX, pipemode | PIPE_WAIT,  
         /* nMaxInstances */ 1,  
         /* nOutBufSize */ 1024,  
         /* nInBufSize */ 1024,  
         /* nDefaultWait */ NMPWAIT_USE_DEFAULT_WAIT,  
         /* lpSecurityAttrib */ NULL);  
   
     if (hnp == INVALID_HANDLE_VALUE && GetLastError() == ERROR_CALL_NOT_IMPLEMENTED) {  
         /* Is this the right way to notify user of skipped tests? */  
         ok(hnp == INVALID_HANDLE_VALUE && GetLastError() == ERROR_CALL_NOT_IMPLEMENTED,  
             "CreateNamedPipe not supported on this platform, skipping tests.\n");  
         return;  
     }  
     ok(hnp == INVALID_HANDLE_VALUE && GetLastError() == ERROR_INVALID_NAME,  
         "CreateNamedPipe should fail if name doesn't start with \\\\.\\pipe\n");  
   
     hnp = CreateNamedPipe(NULL,  
         PIPE_ACCESS_DUPLEX, pipemode | PIPE_WAIT,  
         1, 1024, 1024, NMPWAIT_USE_DEFAULT_WAIT, NULL);  
     ok(hnp == INVALID_HANDLE_VALUE && GetLastError() == ERROR_PATH_NOT_FOUND,  
         "CreateNamedPipe should fail if name is NULL\n");  
   
     hFile = CreateFileA(PIPENAME, GENERIC_READ | GENERIC_WRITE, 0, NULL, OPEN_EXISTING, 0, 0);  
     ok(hFile == INVALID_HANDLE_VALUE  
         && GetLastError() == ERROR_FILE_NOT_FOUND,  
         "connecting to nonexistent named pipe should fail with ERROR_FILE_NOT_FOUND\n");  
   
     /* Functional checks */  
   
     hnp = CreateNamedPipe(PIPENAME, PIPE_ACCESS_DUPLEX, pipemode | PIPE_WAIT,  
         /* nMaxInstances */ 1,  
         /* nOutBufSize */ 1024,  
         /* nInBufSize */ 1024,  
         /* nDefaultWait */ NMPWAIT_USE_DEFAULT_WAIT,  
         /* lpSecurityAttrib */ NULL);  
     ok(hnp != INVALID_HANDLE_VALUE, "CreateNamedPipe failed\n");  
   
     hFile = CreateFileA(PIPENAME, GENERIC_READ | GENERIC_WRITE, 0, NULL, OPEN_EXISTING, 0, 0);  
     ok(hFile != INVALID_HANDLE_VALUE, "CreateFile failed\n");  
   
     /* don't try to do i/o if one side couldn't be opened, as it hangs */  
     if (hFile != INVALID_HANDLE_VALUE) {  
         HANDLE hFile2;  
   
         /* Make sure we can read and write a few bytes in both directions */  
         memset(ibuf, 0, sizeof(ibuf));  
         ok(WriteFile(hnp, obuf, sizeof(obuf), &written, NULL), "WriteFile\n");  
         ok(written == sizeof(obuf), "write file len 1\n");  
         ok(PeekNamedPipe(hFile, NULL, 0, NULL, &readden, NULL), "Peek\n");  
         ok(readden == sizeof(obuf), "peek 1 got %ld bytes\n", readden);  
         ok(ReadFile(hFile, ibuf, sizeof(ibuf), &readden, NULL), "ReadFile\n");  
         ok(readden == sizeof(obuf), "read 1 got %ld bytes\n", readden);  
         ok(memcmp(obuf, ibuf, written) == 0, "content 1 check\n");  
   
         memset(ibuf, 0, sizeof(ibuf));  
         ok(WriteFile(hFile, obuf2, sizeof(obuf2), &written, NULL), "WriteFile\n");  
         ok(written == sizeof(obuf2), "write file len 2\n");  
         ok(PeekNamedPipe(hnp, NULL, 0, NULL, &readden, NULL), "Peek\n");  
         ok(readden == sizeof(obuf2), "peek 2 got %ld bytes\n", readden);  
         ok(ReadFile(hnp, ibuf, sizeof(ibuf), &readden, NULL), "ReadFile\n");  
         ok(readden == sizeof(obuf2), "read 2 got %ld bytes\n", readden);  
         ok(memcmp(obuf2, ibuf, written) == 0, "content 2 check\n");  
   
         /* Test reading of multiple writes */  
         memset(ibuf, 0, sizeof(ibuf));  
         ok(WriteFile(hnp, obuf, sizeof(obuf), &written, NULL), "WriteFile3a\n");  
         ok(written == sizeof(obuf), "write file len 3a\n");  
         ok(WriteFile(hnp, obuf2, sizeof(obuf2), &written, NULL), " WriteFile3b\n");  
         ok(written == sizeof(obuf2), "write file len 3b\n");  
         ok(PeekNamedPipe(hFile, ibuf, sizeof(ibuf), &readden, &avail, NULL), "Peek3\n");  
         if (pipemode == PIPE_TYPE_BYTE) {  
             todo_wine {  
                 /* should return all 23 bytes */  
                 ok(readden == sizeof(obuf) + sizeof(obuf2), "peek3 got %ld bytes\n", readden);  
             }  
         }  
         else  
             ok(readden == sizeof(obuf), "peek3 got %ld bytes\n", readden);  
         todo_wine {  
             ok(avail == sizeof(obuf) + sizeof(obuf2), "peek3 got %ld bytes available\n", avail);  
         }  
         pbuf = ibuf;  
         ok(memcmp(obuf, pbuf, sizeof(obuf)) == 0, "pipe content 3a check\n");  
         if (pipemode == PIPE_TYPE_BYTE) {  
             todo_wine {  
                 pbuf += sizeof(obuf);  
                 ok(memcmp(obuf2, pbuf, sizeof(obuf2)) == 0, "pipe content 3b check\n");  
             }  
         }  
         ok(ReadFile(hFile, ibuf, sizeof(ibuf), &readden, NULL), "ReadFile\n");  
         ok(readden == sizeof(obuf) + sizeof(obuf2), "read 3 got %ld bytes\n", readden);  
         pbuf = ibuf;  
         ok(memcmp(obuf, pbuf, sizeof(obuf)) == 0, "content 3a check\n");  
         pbuf += sizeof(obuf);  
         ok(memcmp(obuf2, pbuf, sizeof(obuf2)) == 0, "content 3b check\n");  
   
         /* Multiple writes in the reverse direction */  
         memset(ibuf, 0, sizeof(ibuf));  
         ok(WriteFile(hFile, obuf, sizeof(obuf), &written, NULL), "WriteFile4a\n");  
         ok(written == sizeof(obuf), "write file len 4a\n");  
         ok(WriteFile(hFile, obuf2, sizeof(obuf2), &written, NULL), " WriteFile4b\n");  
         ok(written == sizeof(obuf2), "write file len 4b\n");  
         ok(PeekNamedPipe(hnp, ibuf, sizeof(ibuf), &readden, &avail, NULL), "Peek4\n");  
         if (pipemode == PIPE_TYPE_BYTE) {  
             todo_wine {  
                 /* should return all 23 bytes */  
                 ok(readden == sizeof(obuf) + sizeof(obuf2), "peek4 got %ld bytes\n", readden);  
             }  
         }  
         else  
             ok(readden == sizeof(obuf), "peek4 got %ld bytes\n", readden);  
         todo_wine {  
             ok(avail == sizeof(obuf) + sizeof(obuf2), "peek4 got %ld bytes available\n", avail);  
         }  
         pbuf = ibuf;  
         ok(memcmp(obuf, pbuf, sizeof(obuf)) == 0, "pipe content 4a check\n");  
         if (pipemode == PIPE_TYPE_BYTE) {  
             todo_wine {  
                 pbuf += sizeof(obuf);  
                 ok(memcmp(obuf2, pbuf, sizeof(obuf2)) == 0, "pipe content 4b check\n");  
             }  
         }  
         ok(ReadFile(hnp, ibuf, sizeof(ibuf), &readden, NULL), "ReadFile\n");  
         if (pipemode == PIPE_TYPE_BYTE) {  
             ok(readden == sizeof(obuf) + sizeof(obuf2), "read 4 got %ld bytes\n", readden);  
         }  
         else {  
             todo_wine {  
                 ok(readden == sizeof(obuf), "read 4 got %ld bytes\n", readden);  
             }  
         }  
         pbuf = ibuf;  
         ok(memcmp(obuf, pbuf, sizeof(obuf)) == 0, "content 4a check\n");  
         if (pipemode == PIPE_TYPE_BYTE) {  
             pbuf += sizeof(obuf);  
             ok(memcmp(obuf2, pbuf, sizeof(obuf2)) == 0, "content 4b check\n");  
         }  
   
         /* Test reading of multiple writes after a mode change  
           (CreateFile always creates a byte mode pipe) */  
         lpmode = PIPE_READMODE_MESSAGE;  
         if (pipemode == PIPE_TYPE_BYTE) {  
             /* trying to change the client end of a byte pipe to message mode should fail */  
             ok(!SetNamedPipeHandleState(hFile, &lpmode, NULL, NULL), "Change mode\n");  
         }  
         else {  
             todo_wine {  
                 ok(SetNamedPipeHandleState(hFile, &lpmode, NULL, NULL), "Change mode\n");  
             }  
   
             memset(ibuf, 0, sizeof(ibuf));  
             ok(WriteFile(hnp, obuf, sizeof(obuf), &written, NULL), "WriteFile5a\n");  
             ok(written == sizeof(obuf), "write file len 3a\n");  
             ok(WriteFile(hnp, obuf2, sizeof(obuf2), &written, NULL), " WriteFile5b\n");  
             ok(written == sizeof(obuf2), "write file len 3b\n");  
             ok(PeekNamedPipe(hFile, ibuf, sizeof(ibuf), &readden, &avail, NULL), "Peek5\n");  
             ok(readden == sizeof(obuf), "peek5 got %ld bytes\n", readden);  
             todo_wine {  
                 ok(avail == sizeof(obuf) + sizeof(obuf2), "peek5 got %ld bytes available\n", avail);  
             }  
             pbuf = ibuf;  
             ok(memcmp(obuf, pbuf, sizeof(obuf)) == 0, "content 5a check\n");  
             ok(ReadFile(hFile, ibuf, sizeof(ibuf), &readden, NULL), "ReadFile\n");  
             todo_wine {  
                 ok(readden == sizeof(obuf), "read 5 got %ld bytes\n", readden);  
             }  
             pbuf = ibuf;  
             ok(memcmp(obuf, pbuf, sizeof(obuf)) == 0, "content 5a check\n");  
   
             /* Multiple writes in the reverse direction */  
             /* the write of obuf2 from write4 should still be in the buffer */  
             ok(PeekNamedPipe(hnp, ibuf, sizeof(ibuf), &readden, &avail, NULL), "Peek6a\n");  
             todo_wine {  
                 ok(readden == sizeof(obuf2), "peek6a got %ld bytes\n", readden);  
                 ok(avail == sizeof(obuf2), "peek6a got %ld bytes available\n", avail);  
             }  
             if (avail > 0) {  
                 ok(ReadFile(hnp, ibuf, sizeof(ibuf), &readden, NULL), "ReadFile\n");  
                 ok(readden == sizeof(obuf2), "read 6a got %ld bytes\n", readden);  
                 pbuf = ibuf;  
                 ok(memcmp(obuf2, pbuf, sizeof(obuf2)) == 0, "content 6a check\n");  
             }  
             memset(ibuf, 0, sizeof(ibuf));  
             ok(WriteFile(hFile, obuf, sizeof(obuf), &written, NULL), "WriteFile6a\n");  
             ok(written == sizeof(obuf), "write file len 6a\n");  
             ok(WriteFile(hFile, obuf2, sizeof(obuf2), &written, NULL), " WriteFile6b\n");  
             ok(written == sizeof(obuf2), "write file len 6b\n");  
             ok(PeekNamedPipe(hnp, ibuf, sizeof(ibuf), &readden, &avail, NULL), "Peek6\n");  
             ok(readden == sizeof(obuf), "peek6 got %ld bytes\n", readden);  
             todo_wine {  
                 ok(avail == sizeof(obuf) + sizeof(obuf2), "peek6b got %ld bytes available\n", avail);  
             }  
             pbuf = ibuf;  
             ok(memcmp(obuf, pbuf, sizeof(obuf)) == 0, "content 6a check\n");  
             ok(ReadFile(hnp, ibuf, sizeof(ibuf), &readden, NULL), "ReadFile\n");  
             todo_wine {  
                 ok(readden == sizeof(obuf), "read 6b got %ld bytes\n", readden);  
             }  
             pbuf = ibuf;  
             ok(memcmp(obuf, pbuf, sizeof(obuf)) == 0, "content 6a check\n");  
         }  
   
         /* Picky conformance tests */  
   
         /* Verify that you can't connect to pipe again  
          * until server calls DisconnectNamedPipe+ConnectNamedPipe  
          * or creates a new pipe  
          * case 1: other client not yet closed  
          */  
         hFile2 = CreateFileA(PIPENAME, GENERIC_READ | GENERIC_WRITE, 0, NULL, OPEN_EXISTING, 0, 0);  
         ok(hFile2 == INVALID_HANDLE_VALUE,  
             "connecting to named pipe after other client closes but before DisconnectNamedPipe should fail\n");  
         ok(GetLastError() == ERROR_PIPE_BUSY,  
             "connecting to named pipe before other client closes should fail with ERROR_PIPE_BUSY\n");  
   
         ok(CloseHandle(hFile), "CloseHandle\n");  
   
         /* case 2: other client already closed */  
         hFile = CreateFileA(PIPENAME, GENERIC_READ | GENERIC_WRITE, 0, NULL, OPEN_EXISTING, 0, 0);  
         ok(hFile == INVALID_HANDLE_VALUE,  
             "connecting to named pipe after other client closes but before DisconnectNamedPipe should fail\n");  
         ok(GetLastError() == ERROR_PIPE_BUSY,  
             "connecting to named pipe after other client closes but before DisconnectNamedPipe should fail with ERROR_PIPE_BUSY\n");  
   
         ok(DisconnectNamedPipe(hnp), "DisconnectNamedPipe\n");  
   
         /* case 3: server has called DisconnectNamedPipe but not ConnectNamed Pipe */  
         hFile = CreateFileA(PIPENAME, GENERIC_READ | GENERIC_WRITE, 0, NULL, OPEN_EXISTING, 0, 0);  
         ok(hFile == INVALID_HANDLE_VALUE,  
             "connecting to named pipe after other client closes but before DisconnectNamedPipe should fail\n");  
         ok(GetLastError() == ERROR_PIPE_BUSY,  
             "connecting to named pipe after other client closes but before ConnectNamedPipe should fail with ERROR_PIPE_BUSY\n");  
   
         /* to be complete, we'd call ConnectNamedPipe here and loop,  
          * but by default that's blocking, so we'd either have  
          * to turn on the uncommon nonblocking mode, or  
          * use another thread.  
          */  
     }     }
           trace("socket() ok\n");
  
     ok(CloseHandle(hnp), "CloseHandle\n");          addr->sin_family = AF_INET;
           addr->sin_addr.s_addr = INADDR_ANY;
           addr->sin_port = htons(0);
  
     trace("test_CreateNamedPipe returning\n");          if( bind(*sock, (const SOCKADDR *) addr, sizeof(*addr)) ) {
                   ok( 0 , "Error binding client to socket");
                   WSACleanup();
                   exit(0);
 } }
  
 void test_CreateNamedPipe_instances_must_match(void)          // get port number
           tmpAddrSize = sizeof(tmpAddr);
           getsockname(*sock, (SOCKADDR *) &tmpAddr, &tmpAddrSize);
           addr->sin_port = tmpAddr.sin_port;
   }
   
   void BlockingClient(int *serverPort)
 { {
     HANDLE hnp, hnp2;          SOCKET sock;
           SOCKADDR_IN client, server;
           HOSTENT *hp;
           char* msg="Some message to send to server";
  
     /* Check no mismatch */          StartNetworkApp(SOCK_STREAM, &sock, &client);
     hnp = CreateNamedPipe(PIPENAME, PIPE_ACCESS_DUPLEX, PIPE_TYPE_BYTE | PIPE_WAIT,  
         /* nMaxInstances */ 2,  
         /* nOutBufSize */ 1024,  
         /* nInBufSize */ 1024,  
         /* nDefaultWait */ NMPWAIT_USE_DEFAULT_WAIT,  
         /* lpSecurityAttrib */ NULL);  
     ok(hnp != INVALID_HANDLE_VALUE, "CreateNamedPipe failed\n");  
   
     hnp2 = CreateNamedPipe(PIPENAME, PIPE_ACCESS_DUPLEX, PIPE_TYPE_BYTE | PIPE_WAIT,  
         /* nMaxInstances */ 2,  
         /* nOutBufSize */ 1024,  
         /* nInBufSize */ 1024,  
         /* nDefaultWait */ NMPWAIT_USE_DEFAULT_WAIT,  
         /* lpSecurityAttrib */ NULL);  
     ok(hnp2 != INVALID_HANDLE_VALUE, "CreateNamedPipe failed\n");  
   
     ok(CloseHandle(hnp), "CloseHandle\n");  
     ok(CloseHandle(hnp2), "CloseHandle\n");  
   
     /* Check nMaxInstances */  
     hnp = CreateNamedPipe(PIPENAME, PIPE_ACCESS_DUPLEX, PIPE_TYPE_BYTE | PIPE_WAIT,  
         /* nMaxInstances */ 1,  
         /* nOutBufSize */ 1024,  
         /* nInBufSize */ 1024,  
         /* nDefaultWait */ NMPWAIT_USE_DEFAULT_WAIT,  
         /* lpSecurityAttrib */ NULL);  
     ok(hnp != INVALID_HANDLE_VALUE, "CreateNamedPipe failed\n");  
   
     hnp2 = CreateNamedPipe(PIPENAME, PIPE_ACCESS_DUPLEX, PIPE_TYPE_BYTE | PIPE_WAIT,  
         /* nMaxInstances */ 1,  
         /* nOutBufSize */ 1024,  
         /* nInBufSize */ 1024,  
         /* nDefaultWait */ NMPWAIT_USE_DEFAULT_WAIT,  
         /* lpSecurityAttrib */ NULL);  
     ok(hnp2 == INVALID_HANDLE_VALUE  
         && GetLastError() == ERROR_PIPE_BUSY, "nMaxInstances not obeyed\n");  
   
     ok(CloseHandle(hnp), "CloseHandle\n");  
   
     /* Check PIPE_ACCESS_* */  
     hnp = CreateNamedPipe(PIPENAME, PIPE_ACCESS_DUPLEX, PIPE_TYPE_BYTE | PIPE_WAIT,  
         /* nMaxInstances */ 2,  
         /* nOutBufSize */ 1024,  
         /* nInBufSize */ 1024,  
         /* nDefaultWait */ NMPWAIT_USE_DEFAULT_WAIT,  
         /* lpSecurityAttrib */ NULL);  
     ok(hnp != INVALID_HANDLE_VALUE, "CreateNamedPipe failed\n");  
   
     hnp2 = CreateNamedPipe(PIPENAME, PIPE_ACCESS_INBOUND, PIPE_TYPE_BYTE | PIPE_WAIT,  
         /* nMaxInstances */ 1,  
         /* nOutBufSize */ 1024,  
         /* nInBufSize */ 1024,  
         /* nDefaultWait */ NMPWAIT_USE_DEFAULT_WAIT,  
         /* lpSecurityAttrib */ NULL);  
     ok(hnp2 == INVALID_HANDLE_VALUE  
         && GetLastError() == ERROR_ACCESS_DENIED, "PIPE_ACCESS_* mismatch allowed\n");  
  
     ok(CloseHandle(hnp), "CloseHandle\n");          hp = gethostbyname("localhost");
  
     /* etc, etc */          while(*serverPort == 0) ;
 }  
  
 /** implementation of alarm() */          // network code here
 static DWORD CALLBACK alarmThreadMain(LPVOID arg)          server.sin_family = AF_INET;
 {          server.sin_addr = *(struct in_addr *) hp->h_addr;
     DWORD timeout = (DWORD) arg;          server.sin_port = *serverPort;
     trace("alarmThreadMain\n");  
     if (WaitForSingleObject( alarm_event, timeout ) == WAIT_TIMEOUT)          if(connect(sock, (struct sockaddr *)&server, sizeof(struct sockaddr)) < 0){
     {                  ok( 0 , "Error connecting client to socket\n");
         ok(FALSE, "alarm\n");                  WSACleanup();
         ExitProcess(1);                  exit(0);
     }     }
     return 1;  
           if((send(sock, msg, strlen(msg), 0))==-1){
                   ok( 0 , "Error sending message\n");
                   WSACleanup();
                   exit(0);
 } }
  
 HANDLE hnp = INVALID_HANDLE_VALUE;          trace("blocking client done\n");
           clientsDone++;
   }
  
 /** Trivial byte echo server - disconnects after each session */  void ProcessConnection(SOCKET *ConnectedSocket)
 static DWORD CALLBACK serverThreadMain1(LPVOID arg)  
 { {
     int i;          // this will handle all connections to the server, it's in its own function to allow for multithreading
           int bClosed;
     trace("serverThreadMain1 start\n");          bClosed = close(ConnectedSocket);
     /* Set up a simple echo server */          //ok(bClosed,"Error closing socket");
     hnp = CreateNamedPipe(PIPENAME "serverThreadMain1", PIPE_ACCESS_DUPLEX,  
         PIPE_TYPE_BYTE | PIPE_WAIT,  
         /* nMaxInstances */ 1,  
         /* nOutBufSize */ 1024,  
         /* nInBufSize */ 1024,  
         /* nDefaultWait */ NMPWAIT_USE_DEFAULT_WAIT,  
         /* lpSecurityAttrib */ NULL);  
   
     ok(hnp != INVALID_HANDLE_VALUE, "CreateNamedPipe failed\n");  
     for (i = 0; i < NB_SERVER_LOOPS; i++) {  
         char buf[512];  
         DWORD written;  
         DWORD readden;  
         DWORD success;  
   
         /* Wait for client to connect */  
         trace("Server calling ConnectNamedPipe...\n");  
         ok(ConnectNamedPipe(hnp, NULL)  
             || GetLastError() == ERROR_PIPE_CONNECTED, "ConnectNamedPipe\n");  
         trace("ConnectNamedPipe returned.\n");  
   
         /* Echo bytes once */  
         memset(buf, 0, sizeof(buf));  
   
         trace("Server reading...\n");  
         success = ReadFile(hnp, buf, sizeof(buf), &readden, NULL);  
         trace("Server done reading.\n");  
         ok(success, "ReadFile\n");  
         ok(readden, "short read\n");  
   
         trace("Server writing...\n");  
         ok(WriteFile(hnp, buf, readden, &written, NULL), "WriteFile\n");  
         trace("Server done writing.\n");  
         ok(written == readden, "write file len\n");  
   
         /* finish this connection, wait for next one */  
         ok(FlushFileBuffers(hnp), "FlushFileBuffers\n");  
         trace("Server done flushing.\n");  
         ok(DisconnectNamedPipe(hnp), "DisconnectNamedPipe\n");  
         trace("Server done disconnecting.\n");  
     }  
     return 0;  
 } }
  
 /** Trivial byte echo server - closes after each connection */  void BlockingServer(int *port) // listens for incoming connections and accepts up to NUM_CLIENTS connections at once
 static DWORD CALLBACK serverThreadMain2(LPVOID arg)  
 { {
     int i;          struct ServerThread *Threads;
     HANDLE hnpNext = 0;          HANDLE* ServerThreads; // the handles for the threads that process connections
           DWORD* ServerThreadIDs; // the thread ids for the threads that process connections
           SOCKET* ConnectedSockets; // the threads created by accept() that get sent to the processing function
           int ThreadIndex = 0;
  
     trace("serverThreadMain2\n");          SOCKET sock;
     /* Set up a simple echo server */          SOCKADDR_IN server;
     hnp = CreateNamedPipe(PIPENAME "serverThreadMain2", PIPE_ACCESS_DUPLEX,          int ListenReturn;
         PIPE_TYPE_BYTE | PIPE_WAIT,  
         /* nMaxInstances */ 2,  
         /* nOutBufSize */ 1024,  
         /* nInBufSize */ 1024,  
         /* nDefaultWait */ NMPWAIT_USE_DEFAULT_WAIT,  
         /* lpSecurityAttrib */ NULL);  
     ok(hnp != INVALID_HANDLE_VALUE, "CreateNamedPipe failed\n");  
   
     for (i = 0; i < NB_SERVER_LOOPS; i++) {  
         char buf[512];  
         DWORD written;  
         DWORD readden;  
         DWORD success;  
   
         /* Wait for client to connect */  
         trace("Server calling ConnectNamedPipe...\n");  
         ok(ConnectNamedPipe(hnp, NULL)  
             || GetLastError() == ERROR_PIPE_CONNECTED, "ConnectNamedPipe\n");  
         trace("ConnectNamedPipe returned.\n");  
   
         /* Echo bytes once */  
         memset(buf, 0, sizeof(buf));  
   
         trace("Server reading...\n");  
         success = ReadFile(hnp, buf, sizeof(buf), &readden, NULL);  
         trace("Server done reading.\n");  
         ok(success, "ReadFile\n");  
   
         trace("Server writing...\n");  
         ok(WriteFile(hnp, buf, readden, &written, NULL), "WriteFile\n");  
         trace("Server done writing.\n");  
         ok(written == readden, "write file len\n");  
   
         /* finish this connection, wait for next one */  
         ok(FlushFileBuffers(hnp), "FlushFileBuffers\n");  
         ok(DisconnectNamedPipe(hnp), "DisconnectNamedPipe\n");  
   
         /* Set up next echo server */  
         hnpNext =  
             CreateNamedPipe(PIPENAME "serverThreadMain2", PIPE_ACCESS_DUPLEX,  
             PIPE_TYPE_BYTE | PIPE_WAIT,  
             /* nMaxInstances */ 2,  
             /* nOutBufSize */ 1024,  
             /* nInBufSize */ 1024,  
             /* nDefaultWait */ NMPWAIT_USE_DEFAULT_WAIT,  
             /* lpSecurityAttrib */ NULL);  
   
         ok(hnpNext != INVALID_HANDLE_VALUE, "CreateNamedPipe failed\n");  
  
         ok(CloseHandle(hnp), "CloseHandle\n");          StartNetworkApp(SOCK_STREAM, &sock, &server);
         hnp = hnpNext;          *port = server.sin_port;
     }  
     return 0;  
 }  
  
 /** Trivial byte echo server - uses overlapped named pipe calls */          Threads = malloc(sizeof(struct ServerThread) * NUM_CLIENTS);
 static DWORD CALLBACK serverThreadMain3(LPVOID arg)          memset(Threads, 0, sizeof(struct ServerThread) * NUM_CLIENTS);
 {  
     int i;  
     HANDLE hEvent;  
  
     trace("serverThreadMain3\n");          ServerThreads = malloc(sizeof(HANDLE) * NUM_CLIENTS);
     /* Set up a simple echo server */          memset(ServerThreads, 0, sizeof(HANDLE) * NUM_CLIENTS);
     hnp = CreateNamedPipe(PIPENAME "serverThreadMain3", PIPE_ACCESS_DUPLEX | FILE_FLAG_OVERLAPPED,  
         PIPE_TYPE_BYTE | PIPE_WAIT,  
         /* nMaxInstances */ 1,  
         /* nOutBufSize */ 1024,  
         /* nInBufSize */ 1024,  
         /* nDefaultWait */ NMPWAIT_USE_DEFAULT_WAIT,  
         /* lpSecurityAttrib */ NULL);  
     ok(hnp != INVALID_HANDLE_VALUE, "CreateNamedPipe failed\n");  
   
     hEvent = CreateEvent(NULL,  /* security attribute */  
         TRUE,                   /* manual reset event */  
         FALSE,                  /* initial state */  
         NULL);                  /* name */  
     ok(hEvent != NULL, "CreateEvent\n");  
   
     for (i = 0; i < NB_SERVER_LOOPS; i++) {  
         char buf[512];  
         DWORD written;  
         DWORD readden;  
         DWORD dummy;  
         DWORD success;  
         OVERLAPPED oOverlap;  
         int letWFSOEwait = (i & 2);  
         int letGORwait = (i & 1);  
         DWORD err;  
   
         memset(&oOverlap, 0, sizeof(oOverlap));  
         oOverlap.hEvent = hEvent;  
   
         /* Wait for client to connect */  
         trace("Server calling overlapped ConnectNamedPipe...\n");  
         success = ConnectNamedPipe(hnp, &oOverlap);  
         err = GetLastError();  
         ok(success || err == ERROR_IO_PENDING  
             || err == ERROR_PIPE_CONNECTED, "overlapped ConnectNamedPipe\n");  
         trace("overlapped ConnectNamedPipe returned.\n");  
         if (!success && (err == ERROR_IO_PENDING) && letWFSOEwait)  
             ok(WaitForSingleObjectEx(hEvent, INFINITE, TRUE) == 0, "wait ConnectNamedPipe\n");  
         success = GetOverlappedResult(hnp, &oOverlap, &dummy, letGORwait);  
         if (!letGORwait && !letWFSOEwait && !success) {  
             ok(GetLastError() == ERROR_IO_INCOMPLETE, "GetOverlappedResult\n");  
             success = GetOverlappedResult(hnp, &oOverlap, &dummy, TRUE);  
         }  
         ok(success, "GetOverlappedResult ConnectNamedPipe\n");  
         trace("overlapped ConnectNamedPipe operation complete.\n");  
   
         /* Echo bytes once */  
         memset(buf, 0, sizeof(buf));  
   
         trace("Server reading...\n");  
         success = ReadFile(hnp, buf, sizeof(buf), NULL, &oOverlap);  
         trace("Server ReadFile returned...\n");  
         err = GetLastError();  
         ok(success || err == ERROR_IO_PENDING, "overlapped ReadFile\n");  
         trace("overlapped ReadFile returned.\n");  
         if (!success && (err == ERROR_IO_PENDING) && letWFSOEwait)  
             ok(WaitForSingleObjectEx(hEvent, INFINITE, TRUE) == 0, "wait ReadFile\n");  
         success = GetOverlappedResult(hnp, &oOverlap, &readden, letGORwait);  
         if (!letGORwait && !letWFSOEwait && !success) {  
             ok(GetLastError() == ERROR_IO_INCOMPLETE, "GetOverlappedResult\n");  
             success = GetOverlappedResult(hnp, &oOverlap, &readden, TRUE);  
         }  
         trace("Server done reading.\n");  
         ok(success, "overlapped ReadFile\n");  
   
         trace("Server writing...\n");  
         success = WriteFile(hnp, buf, readden, NULL, &oOverlap);  
         trace("Server WriteFile returned...\n");  
         err = GetLastError();  
         ok(success || err == ERROR_IO_PENDING, "overlapped WriteFile\n");  
         trace("overlapped WriteFile returned.\n");  
         if (!success && (err == ERROR_IO_PENDING) && letWFSOEwait)  
             ok(WaitForSingleObjectEx(hEvent, INFINITE, TRUE) == 0, "wait WriteFile\n");  
         success = GetOverlappedResult(hnp, &oOverlap, &written, letGORwait);  
         if (!letGORwait && !letWFSOEwait && !success) {  
             ok(GetLastError() == ERROR_IO_INCOMPLETE, "GetOverlappedResult\n");  
             success = GetOverlappedResult(hnp, &oOverlap, &written, TRUE);  
         }  
         trace("Server done writing.\n");  
         ok(success, "overlapped WriteFile\n");  
         ok(written == readden, "write file len\n");  
   
         /* finish this connection, wait for next one */  
         ok(FlushFileBuffers(hnp), "FlushFileBuffers\n");  
         ok(DisconnectNamedPipe(hnp), "DisconnectNamedPipe\n");  
     }  
     return 0;  
 }  
  
 static void exercizeServer(const char *pipename, HANDLE serverThread)          ServerThreadIDs = malloc(sizeof(DWORD) * NUM_CLIENTS);
 {          memset(ServerThreadIDs, 0, sizeof(DWORD) * NUM_CLIENTS);
     int i;  
  
     trace("exercizeServer starting\n");          ConnectedSockets = malloc(sizeof(DWORD) * NUM_CLIENTS);
     for (i = 0; i < NB_SERVER_LOOPS; i++) {          memset(ConnectedSockets, 0, sizeof(DWORD) * NUM_CLIENTS);
         HANDLE hFile=INVALID_HANDLE_VALUE;  
         static const char obuf[] = "Bit Bucket";  
         char ibuf[32];  
         DWORD written;  
         DWORD readden;  
         int loop;  
   
         for (loop = 0; loop < 3; loop++) {  
             DWORD err;  
             trace("Client connecting...\n");  
             /* Connect to the server */  
             hFile = CreateFileA(pipename, GENERIC_READ | GENERIC_WRITE, 0,  
                 NULL, OPEN_EXISTING, 0, 0);  
             if (hFile != INVALID_HANDLE_VALUE)  
                 break;  
             err = GetLastError();  
             if (loop == 0)  
                 ok(err == ERROR_PIPE_BUSY || err == ERROR_FILE_NOT_FOUND, "connecting to pipe\n");  
             else  
                 ok(err == ERROR_PIPE_BUSY, "connecting to pipe\n");  
             trace("connect failed, retrying\n");  
             Sleep(200);  
         }  
         ok(hFile != INVALID_HANDLE_VALUE, "client opening named pipe\n");  
   
         /* Make sure it can echo */  
         memset(ibuf, 0, sizeof(ibuf));  
         trace("Client writing...\n");  
         ok(WriteFile(hFile, obuf, sizeof(obuf), &written, NULL), "WriteFile to client end of pipe\n");  
         ok(written == sizeof(obuf), "write file len\n");  
         trace("Client reading...\n");  
         ok(ReadFile(hFile, ibuf, sizeof(obuf), &readden, NULL), "ReadFile from client end of pipe\n");  
         ok(readden == sizeof(obuf), "read file len\n");  
         ok(memcmp(obuf, ibuf, written) == 0, "content check\n");  
   
         trace("Client closing...\n");  
         ok(CloseHandle(hFile), "CloseHandle\n");  
     }  
   
     ok(WaitForSingleObject(serverThread,INFINITE) == WAIT_OBJECT_0, "WaitForSingleObject\n");  
     CloseHandle(hnp);  
     trace("exercizeServer returning\n");  
 }  
  
 static void test_NamedPipe_2(void)          //SOCKADDR_IN RemoteAddress;
 {  
     HANDLE serverThread;  
     DWORD serverThreadId;  
     HANDLE alarmThread;  
     DWORD alarmThreadId;  
   
     trace("test_NamedPipe_2 starting\n");  
     /* Set up a ten second timeout */  
     alarm_event = CreateEvent( NULL, TRUE, FALSE, NULL );  
     alarmThread = CreateThread(NULL, 0, alarmThreadMain, (void *) 10000, 0, &alarmThreadId);  
   
     /* The servers we're about to exercize do try to clean up carefully,  
      * but to reduce the change of a test failure due to a pipe handle  
      * leak in the test code, we'll use a different pipe name for each server.  
      */  
  
     /* Try server #1 */          ListenReturn = listen(sock, 5);
     serverThread = CreateThread(NULL, 0, serverThreadMain1, (void *)8, 0, &serverThreadId);          ok(ListenReturn != SOCKET_ERROR, "error listening on socket");
     ok(serverThread != INVALID_HANDLE_VALUE, "CreateThread\n");  
     exercizeServer(PIPENAME "serverThreadMain1", serverThread);  
   
     /* Try server #2 */  
     serverThread = CreateThread(NULL, 0, serverThreadMain2, 0, 0, &serverThreadId);  
     ok(serverThread != INVALID_HANDLE_VALUE, "CreateThread\n");  
     exercizeServer(PIPENAME "serverThreadMain2", serverThread);  
  
     if( 0 ) /* overlapped pipe server doesn't work yet - it randomly fails */          for (ThreadIndex = 0; ThreadIndex < NUM_CLIENTS; ThreadIndex++)
     {     {
     /* Try server #3 */                          ConnectedSockets[ThreadIndex] = accept(sock, (SOCKADDR *) &Threads[ThreadIndex].Client, &sizeofSOCKADDR_IN); // this can be modified to include the address of the remote socket
     serverThread = CreateThread(NULL, 0, serverThreadMain3, 0, 0, &serverThreadId);                          ok(ConnectedSockets[ThreadIndex] != INVALID_SOCKET, "error accepting socket");
     ok(serverThread != INVALID_HANDLE_VALUE, "CreateThread\n");  
     exercizeServer(PIPENAME "serverThreadMain3", serverThread);                          ServerThreads[ThreadIndex] = CreateThread(NULL, 0, (LPTHREAD_START_ROUTINE) &ProcessConnection, &ConnectedSockets[ThreadIndex], 0, &ServerThreadIDs[ThreadIndex]);
     }     }
  
     ok(SetEvent( alarm_event ), "SetEvent\n");          // network code here
     CloseHandle( alarm_event );  
     trace("test_NamedPipe_2 returning\n");          free(ServerThreads);
           free(ServerThreadIDs);
           free(ConnectedSockets);
           trace("blocking server done\n");
 } }
  
 static void test_DisconnectNamedPipe(void)  static void test_ClientServerBlocking_1(void)
 { {
     HANDLE hnp;          int ThreadIndex = 0;
     HANDLE hFile;          int serverPort = 0; // I think the server port would work better as a #DEFINE rather than a variable that gets passed around everywhere
     static const char obuf[] = "Bit Bucket";          HANDLE ServerThread;
     char ibuf[32];          DWORD ServerThreadId;
     DWORD written;          DWORD *ClientThreadIds;
     DWORD readden;          HANDLE *ClientThreads;
   
     hnp = CreateNamedPipe(PIPENAME, PIPE_ACCESS_DUPLEX, PIPE_TYPE_BYTE | PIPE_WAIT,  
         /* nMaxInstances */ 1,  
         /* nOutBufSize */ 1024,  
         /* nInBufSize */ 1024,  
         /* nDefaultWait */ NMPWAIT_USE_DEFAULT_WAIT,  
         /* lpSecurityAttrib */ NULL);  
     ok(hnp != INVALID_HANDLE_VALUE, "CreateNamedPipe failed\n");  
   
     ok(WriteFile(hnp, obuf, sizeof(obuf), &written, NULL) == 0  
         && GetLastError() == ERROR_PIPE_LISTENING, "WriteFile to not-yet-connected pipe\n");  
     ok(ReadFile(hnp, ibuf, sizeof(ibuf), &readden, NULL) == 0  
         && GetLastError() == ERROR_PIPE_LISTENING, "ReadFile from not-yet-connected pipe\n");  
  
     hFile = CreateFileA(PIPENAME, GENERIC_READ | GENERIC_WRITE, 0, NULL, OPEN_EXISTING, 0, 0);          ServerThread = CreateThread(NULL, 0, (LPTHREAD_START_ROUTINE) &BlockingClient, &serverPort, 0, &ServerThreadId);
     ok(hFile != INVALID_HANDLE_VALUE, "CreateFile failed\n");  
  
     /* don't try to do i/o if one side couldn't be opened, as it hangs */          ClientThreads = malloc(sizeof(HANDLE) * NUM_CLIENTS);
     if (hFile != INVALID_HANDLE_VALUE) {          memset(ClientThreads, 0, sizeof(HANDLE) * NUM_CLIENTS);
  
         /* see what happens if server calls DisconnectNamedPipe          ClientThreadIds = malloc(sizeof(DWORD) * NUM_CLIENTS);
          * when there are bytes in the pipe          memset(ClientThreadIds, 0, sizeof(DWORD) * NUM_CLIENTS);
          */  
  
         ok(WriteFile(hFile, obuf, sizeof(obuf), &written, NULL), "WriteFile\n");          for(ThreadIndex = 0; ThreadIndex < NUM_CLIENTS; ThreadIndex++) {
         ok(written == sizeof(obuf), "write file len\n");                  ClientThreads[ThreadIndex] = CreateThread(NULL, 0, (LPTHREAD_START_ROUTINE) &BlockingServer, &serverPort, 0, &ClientThreadIds[ThreadIndex]);
         ok(DisconnectNamedPipe(hnp), "DisconnectNamedPipe while messages waiting\n");  
         ok(WriteFile(hFile, obuf, sizeof(obuf), &written, NULL) == 0  
             && GetLastError() == ERROR_PIPE_NOT_CONNECTED, "WriteFile to disconnected pipe\n");  
         ok(ReadFile(hnp, ibuf, sizeof(ibuf), &readden, NULL) == 0  
             && GetLastError() == ERROR_PIPE_NOT_CONNECTED,  
             "ReadFile from disconnected pipe with bytes waiting\n");  
         ok(CloseHandle(hFile), "CloseHandle\n");  
     }     }
  
     ok(CloseHandle(hnp), "CloseHandle\n");          trace("test_ClientServerBlocking_1 done\n");
   }
  
   static void test_Startup(void)
   {
           // initialize application
           WSADATA wsaData;
     int wsastartup_result = WSAStartup(MAKEWORD(1,1), &wsaData);
           if ( (LOBYTE(wsaData.wVersion) != 1) && (HIBYTE(wsaData.wVersion) != 1) )
           {
                   ok( 0 , "WSAStartup returns an incompatible sockets version");
                   WSACleanup();
                   exit(0);
 } }
  
      ok((wsastartup_result == NO_ERROR), "Error in WSAStartup()");
   }
   
   
 START_TEST(wsock32_main) START_TEST(wsock32_main)
 { {
     trace("test 1 of 4:\n");    trace("test 1 of 2:\n");
     test_DisconnectNamedPipe();    test_Startup();
     trace("test 2 of 4:\n");    trace("test 2 of 2:\n");
     test_CreateNamedPipe_instances_must_match();    test_ClientServerBlocking_1();
     trace("test 3 of 4:\n");  
     test_NamedPipe_2();  
     trace("test 4 of 4:\n");  
     test_CreateNamedPipe(PIPE_TYPE_BYTE);  
     trace("all tests done\n");  
     test_CreateNamedPipe(PIPE_TYPE_MESSAGE | PIPE_READMODE_MESSAGE);  
     trace("all tests done\n");     trace("all tests done\n");
           while (clientsDone != NUM_CLIENTS)
                   ;
 } }


Legend:
Removed from v.1.1  
changed lines
  Added in v.1.12

Rizwan Kassim
Powered by
ViewCVS 0.9.2