(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.28

version 1.1, 2005/02/04 03:01:30 version 1.28, 2005/02/24 22:20:13
Line 1 
Line 1 
 /* /*
  * Unit tests for named pipe functions in Wine   * Unit tests for 32-bit WinSock 1.1 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>
  
 #ifndef STANDALONE #ifndef STANDALONE
 #include "wine/test.h" #include "wine/test.h"
Line 45 
Line 42 
 #define todo_wine #define todo_wine
 #endif #endif
  
 #include <wtypes.h>  // clients threads to create
 #include <winerror.h>  #define NUM_CLIENTS 64
  
 #define PIPENAME "\\\\.\\PiPe\\tests_pipe.c"  // amount of data to transfer from each client to server
   #define TEST_DATA_SIZE 145243
  
 #define NB_SERVER_LOOPS 8  // max time (seconds) to run test
   #define TEST_TIMEOUT 10
  
 static HANDLE alarm_event;  // we often pass this size by reference
   int sizeofSOCKADDR_IN = sizeof(SOCKADDR_IN);
  
 static void test_CreateNamedPipe(int pipemode)  // global test data; server sends it to client, then client verifies it
 {  char *gTestData;
     HANDLE hnp;  
     HANDLE hFile;  
     static const char obuf[] = "Bit Bucket";  
     static const char obuf2[] = "More bits";  
     char ibuf[32], *pbuf;  
     DWORD written;  
     DWORD readden;  
     DWORD avail;  
     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.  
          */  
     }  
  
     ok(CloseHandle(hnp), "CloseHandle\n");  struct ThreadInfo {
           HANDLE Handle;
           DWORD ID;
   };
  
     trace("test_CreateNamedPipe returning\n");  struct ServerInfo {
 }          HANDLE threadHandle;
           DWORD threadID;
           SOCKET connectedSocket; // socket to communicate with client
           SOCKADDR_IN clientAddr; // client info
   };
  
 void test_CreateNamedPipe_instances_must_match(void)  static void test_Startup(void);
   static void test_ClientServerBlocking_1(void);
   static void test_Cleanup(void);
   
   static void BlockingClient(int *serverPort);
   static int BlockingServer_Init(int type, SOCKET *sock, SOCKADDR_IN *addr);
   static void BlockingServer(SOCKET *sock);
   static void BlockingServer_ProcessConnection(struct ServerInfo *t);
   
   static void BlockingClient(int *serverPort)
 { {
     HANDLE hnp, hnp2;          SOCKET sock;
           SOCKADDR_IN server;
           HOSTENT *hp;
           int connectError;
           int totCharsReceived = 0;
           int numCharsReceived;
           int memSame;
           char buf[1001];
  
     /* Check no mismatch */          // create socket
     hnp = CreateNamedPipe(PIPENAME, PIPE_ACCESS_DUPLEX, PIPE_TYPE_BYTE | PIPE_WAIT,          sock = socket(AF_INET, SOCK_STREAM, 0);
         /* nMaxInstances */ 2,          ok( sock != INVALID_SOCKET , "Error in socket()\n");
         /* nOutBufSize */ 1024,          if (sock == INVALID_SOCKET) {
         /* nInBufSize */ 1024,                  WSACleanup();
         /* nDefaultWait */ NMPWAIT_USE_DEFAULT_WAIT,                  exit(0);
         /* 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 */          server.sin_family = AF_INET;
           server.sin_addr = *(struct in_addr *) hp->h_addr;
           server.sin_port = *serverPort;
   
           // connect to server
           connectError = connect(sock, (struct sockaddr *)&server, sizeof(struct sockaddr));
           ok( !connectError , "client cannot connect to host\n");
           if(connectError) {
                   WSACleanup();
                   exit(0);
 } }
  
 /** implementation of alarm() */          // start receiving data from server
 static DWORD CALLBACK alarmThreadMain(LPVOID arg)          while( totCharsReceived < TEST_DATA_SIZE ) {
 {                  numCharsReceived = recv(sock, buf, 1000, 0);
     DWORD timeout = (DWORD) arg;                  ok( numCharsReceived > 0, "socket was closed unexpectedly\n" );
     trace("alarmThreadMain\n");  
     if (WaitForSingleObject( alarm_event, timeout ) == WAIT_TIMEOUT)                  // check received data againt global test data
     {                  memSame = ! memcmp(buf,gTestData+totCharsReceived,numCharsReceived);
         ok(FALSE, "alarm\n");                  ok( memSame, "data integrity lost during transfer\n" );
         ExitProcess(1);                  totCharsReceived += numCharsReceived;
     }     }
     return 1;  
 } }
  
 HANDLE hnp = INVALID_HANDLE_VALUE;  // BlockingServer_Init creates socket sock of type type and returns assigned port number in addr.
   // returns server port number
 /** Trivial byte echo server - disconnects after each session */  static int BlockingServer_Init(int type, SOCKET *sock, SOCKADDR_IN *addr)
 static DWORD CALLBACK serverThreadMain1(LPVOID arg)  
 { {
     int i;          SOCKADDR_IN tmpAddr;
           int bindOK;
           int listenReturn;
  
     trace("serverThreadMain1 start\n");          // create socket
     /* Set up a simple echo server */          *sock = socket(AF_INET, type, 0);
     hnp = CreateNamedPipe(PIPENAME "serverThreadMain1", PIPE_ACCESS_DUPLEX,          ok( *sock != INVALID_SOCKET , "Error in socket()\n");
         PIPE_TYPE_BYTE | PIPE_WAIT,          if (*sock == INVALID_SOCKET) {
         /* nMaxInstances */ 1,                  WSACleanup();
         /* nOutBufSize */ 1024,                  exit(0);
         /* 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;  
           addr->sin_family = AF_INET;
           addr->sin_addr.s_addr = INADDR_ANY;
           addr->sin_port = htons(0);
   
           // bind socket to port
           bindOK = !bind(*sock, (const SOCKADDR *) addr, sizeofSOCKADDR_IN);
           ok( bindOK , "Error binding client to socket\n");
           if( !bindOK ) {
                   WSACleanup();
                   exit(0);
 } }
  
 /** Trivial byte echo server - closes after each connection */          // get port number
 static DWORD CALLBACK serverThreadMain2(LPVOID arg)          getsockname(*sock, (SOCKADDR *) &tmpAddr, &sizeofSOCKADDR_IN);
 {          addr->sin_port = tmpAddr.sin_port;
     int i;  
     HANDLE hnpNext = 0;  
  
     trace("serverThreadMain2\n");          // listen on port
     /* Set up a simple echo server */          listenReturn = listen(*sock, NUM_CLIENTS);
     hnp = CreateNamedPipe(PIPENAME "serverThreadMain2", PIPE_ACCESS_DUPLEX,          ok(listenReturn != SOCKET_ERROR, "error listening on socket\n");
         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");          return addr->sin_port;
         hnp = hnpNext;  
     }  
     return 0;  
 } }
  
 /** Trivial byte echo server - uses overlapped named pipe calls */  static void BlockingServer(SOCKET *sock) // listens for incoming connections and accepts up to NUM_CLIENTS connections at once
 static DWORD CALLBACK serverThreadMain3(LPVOID arg)  
 { {
     int i;          struct ServerInfo *threads;
     HANDLE hEvent;          int threadIndex = 0;
   
           // allocate enough space to keep track of NUM_CLIENTS connections
           threads = malloc(sizeof(struct ServerInfo) * NUM_CLIENTS);
           memset(threads, 0, sizeof(struct ServerInfo) * NUM_CLIENTS);
   
           // we require one connection from each client thread
           for (threadIndex = 0; threadIndex < NUM_CLIENTS; threadIndex++) {
                           // accept connection
                           threads[threadIndex].connectedSocket = accept(*sock, (SOCKADDR *) &threads[threadIndex].clientAddr, &sizeofSOCKADDR_IN); // this can be modified to include the address of the remote socket
                           ok(threads[threadIndex].connectedSocket != INVALID_SOCKET, "error accepting socket\n");
   
                           // spawn thread to handle sending data
                           threads[threadIndex].threadHandle = CreateThread(NULL, 0, (LPTHREAD_START_ROUTINE) &BlockingServer_ProcessConnection, &threads[threadIndex], 0, &threads[threadIndex].threadID);
           }
  
     trace("serverThreadMain3\n");          // wait for all clients to receive data before cleaning up
     /* Set up a simple echo server */          for(threadIndex = 0; threadIndex < NUM_CLIENTS; threadIndex++) {
     hnp = CreateNamedPipe(PIPENAME "serverThreadMain3", PIPE_ACCESS_DUPLEX | FILE_FLAG_OVERLAPPED,                  WaitForSingleObject(threads[threadIndex].threadHandle, INFINITE);
         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;  
           free(threads);
 } }
  
 static void exercizeServer(const char *pipename, HANDLE serverThread)  static void BlockingServer_ProcessConnection(struct ServerInfo *t)
 { {
     int i;          // this will handle all connections to the server, it's in its own function to allow for multithreading
           int bClosed;
           int totCharsSent = 0;
           int numCharsSent;
           const int charsPerSend = 2000;
  
     trace("exercizeServer starting\n");          // loop and send data
     for (i = 0; i < NB_SERVER_LOOPS; i++) {          while( totCharsSent < TEST_DATA_SIZE ) {
         HANDLE hFile=INVALID_HANDLE_VALUE;                  numCharsSent = send(t->connectedSocket, gTestData+totCharsSent, (totCharsSent + charsPerSend <= TEST_DATA_SIZE) ? charsPerSend : TEST_DATA_SIZE - totCharsSent, 0);
         static const char obuf[] = "Bit Bucket";                  ok( numCharsSent != SOCKET_ERROR, "socket error\n" );
         char ibuf[32];  
         DWORD written;                  // pass if send buffer is full
         DWORD readden;                  if(numCharsSent == 0) {
         int loop;                          Sleep(100);
   
         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)                  totCharsSent += numCharsSent;
 {          }
     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 */          bClosed = !closesocket(t->connectedSocket);
     serverThread = CreateThread(NULL, 0, serverThreadMain1, (void *)8, 0, &serverThreadId);          ok(bClosed,"Error closing socket\n");
     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 */  static void test_ClientServerBlocking_1(void)
     {     {
     /* Try server #3 */          struct ThreadInfo serverThread;
     serverThread = CreateThread(NULL, 0, serverThreadMain3, 0, 0, &serverThreadId);          DWORD waitStatus;
     ok(serverThread != INVALID_HANDLE_VALUE, "CreateThread\n");          SOCKET sock;
     exercizeServer(PIPENAME "serverThreadMain3", serverThread);          SOCKADDR_IN server;
           int serverPort;
           int threadIndex = 0;
           struct ThreadInfo *clientThreads;
   
           // create socket, bind server and start listening
           serverPort = BlockingServer_Init(SOCK_STREAM, &sock, &server);
   
           // start server thread
           trace("starting server thread\n");
           serverThread.Handle = CreateThread(NULL, 0, (LPTHREAD_START_ROUTINE) &BlockingServer, &sock, 0, &serverThread.ID);
   
           // start client threads
           clientThreads = malloc(sizeof(struct ThreadInfo) * NUM_CLIENTS);
           memset(clientThreads, 0, sizeof(struct ThreadInfo) * NUM_CLIENTS);
   
           for(threadIndex = 0; threadIndex < NUM_CLIENTS; threadIndex++) {
                   clientThreads[threadIndex].Handle = CreateThread(NULL, 0, (LPTHREAD_START_ROUTINE) &BlockingClient, (void *) &serverPort, 0, &clientThreads[threadIndex].ID);
     }     }
           trace("%d clients started\n", NUM_CLIENTS);
   
           // server thread needs to end before cleaning up
           waitStatus = WaitForSingleObject(serverThread.Handle, TEST_TIMEOUT * 1000);
           ok( waitStatus != WAIT_TIMEOUT, "test did not complete in time\n" );
  
     ok(SetEvent( alarm_event ), "SetEvent\n");          // wait for all clients to receive data before cleaning up
     CloseHandle( alarm_event );          for(threadIndex = 0; threadIndex < NUM_CLIENTS; threadIndex++) {
     trace("test_NamedPipe_2 returning\n");                  WaitForSingleObject(clientThreads[threadIndex].Handle, INFINITE);
 } }
  
 static void test_DisconnectNamedPipe(void)          free(clientThreads);
 {  }
     HANDLE hnp;  
     HANDLE hFile;  
     static const char obuf[] = "Bit Bucket";  
     char ibuf[32];  
     DWORD written;  
     DWORD readden;  
   
     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);  static void test_Startup(void)
     ok(hFile != INVALID_HANDLE_VALUE, "CreateFile failed\n");  {
           // initialize application
           WSADATA wsaData;
           int wsastartup_result;
           int versionOK;
  
     /* don't try to do i/o if one side couldn't be opened, as it hangs */          // check for compatible winsock version
     if (hFile != INVALID_HANDLE_VALUE) {          wsastartup_result = WSAStartup(MAKEWORD(1,1), &wsaData);
           versionOK = (LOBYTE(wsaData.wVersion) == 1) && (HIBYTE(wsaData.wVersion) == 1);
  
         /* see what happens if server calls DisconnectNamedPipe          ok( versionOK , "WSAStartup returns an incompatible sockets version\n");
          * when there are bytes in the pipe          if ( !versionOK ) {
          */                  WSACleanup();
                   exit(0);
           }
  
         ok(WriteFile(hFile, obuf, sizeof(obuf), &written, NULL), "WriteFile\n");          ok((wsastartup_result == NO_ERROR), "Error in WSAStartup()\n");
         ok(written == sizeof(obuf), "write file len\n");          trace("startup ok\n");
         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");  static void test_Cleanup(void)
   {
           int cleanupOK;
   
           cleanupOK = ! WSACleanup();
  
           ok( cleanupOK , "error in WSACleanup()\n");
           trace("cleanup ok\n");
 } }
  
 START_TEST(wsock32_main) START_TEST(wsock32_main)
 { {
     trace("test 1 of 4:\n");          const int numTests = 3;
     test_DisconnectNamedPipe();          gTestData = malloc(TEST_DATA_SIZE);
     trace("test 2 of 4:\n");  
     test_CreateNamedPipe_instances_must_match();          trace("test 1 of %d:\n", numTests);
     trace("test 3 of 4:\n");          test_Startup();
     test_NamedPipe_2();  
     trace("test 4 of 4:\n");          trace("test 2 of %d:\n", numTests);
     test_CreateNamedPipe(PIPE_TYPE_BYTE);          test_ClientServerBlocking_1();
     trace("all tests done\n");  
     test_CreateNamedPipe(PIPE_TYPE_MESSAGE | PIPE_READMODE_MESSAGE);          trace("test 3 of %d:\n", numTests);
           test_Cleanup();
   
     trace("all tests done\n");     trace("all tests done\n");
   
           free(gTestData);
 } }


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

Rizwan Kassim
Powered by
ViewCVS 0.9.2