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

version 1.1, 2005/02/04 03:01:30 version 1.30, 2005/02/25 06:39:52
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
    * standalone boilerplate copyright (c) 2004,2005 Dan Kegel
  *  *
  * 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 19 
  * 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>
  
   /* To build outside Wine tree, compile with cl -DSTANDALONE -D_X86_ wsock32_main.c wsock32.lib */
 #ifndef STANDALONE #ifndef STANDALONE
 #include "wine/test.h" #include "wine/test.h"
 #else #else
 #include <assert.h>  #include <stdarg.h>
   #include <stdio.h>
 #define START_TEST(name) main(int argc, char **argv) #define START_TEST(name) main(int argc, char **argv)
 #define ok(condition, msg) \ #define ok(condition, msg) \
         do { \         do { \
                 if(!(condition)) \                 if(!(condition)) \
                 { \                 { \
                         fprintf(stderr,"failed at %d\n",__LINE__); \                         fprintf(stderr,"failed at %d\n",__LINE__); \
                         exit(0); \                          exit(1); \
                 } \                 } \
         } while(0)         } while(0)
  
 #define todo_wine #define todo_wine
   static void trace(const char *s, ...)
   {
           va_list elipsis;
           va_start (elipsis, s);
           vprintf(s, elipsis);
           va_end(elipsis);
   }
 #endif #endif
  
 #include <wtypes.h>  // clients threads to create
 #include <winerror.h>  #define NUM_CLIENTS 64
   
   // amount of data to transfer from each client to server
   #define TEST_DATA_SIZE 145243
  
 #define PIPENAME "\\\\.\\PiPe\\tests_pipe.c"  // max time (seconds) to run test.
   // On a 650 Mhz Linux system with tcpdump running, it takes 8 seconds.
   #define TEST_TIMEOUT 20
  
 #define NB_SERVER_LOOPS 8  // we often pass this size by reference
   int sizeofSOCKADDR_IN = sizeof(SOCKADDR_IN);
  
 static HANDLE alarm_event;  // global test data; server sends it to client, then client verifies it
   char *gTestData;
  
 static void test_CreateNamedPipe(int pipemode)  struct ThreadInfo {
           HANDLE Handle;
           DWORD ID;
   };
   
   struct BlockingServerConnection {
           struct ThreadInfo serverThread;
           SOCKET connectedSocket; // socket to communicate with client
           SOCKADDR_IN clientAddr; // client info
   };
   
   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 struct BlockingServerConnection * BlockingServerConnection_New(SOCKET sock, SOCKADDR_IN clientAddr);
   static void BlockingServerConnection_Run(struct BlockingServerConnection *t);
   static void BlockingServerConnection_Delete(struct BlockingServerConnection *c);
   
   static void BlockingClient(int *serverPort)
 { {
     HANDLE hnp;          SOCKET sock;
     HANDLE hFile;          SOCKADDR_IN server;
     static const char obuf[] = "Bit Bucket";          HOSTENT *hp;
     static const char obuf2[] = "More bits";          int connectError;
     char ibuf[32], *pbuf;          int totCharsReceived = 0;
     DWORD written;          int numCharsReceived;
     DWORD readden;          int memSame;
     DWORD avail;          char buf[1001];
     DWORD lpmode;  
           // create socket
     if (pipemode == PIPE_TYPE_BYTE)          sock = socket(AF_INET, SOCK_STREAM, 0);
         trace("test_CreateNamedPipe starting in byte mode\n");          ok( sock != INVALID_SOCKET , "Error in socket()\n");
     else          if (sock == INVALID_SOCKET) {
         trace("test_CreateNamedPipe starting in message mode\n");                  WSACleanup();
     /* Bad parameter checks */                  exit(0);
     hnp = CreateNamedPipe("not a named pipe", PIPE_ACCESS_DUPLEX, pipemode | PIPE_WAIT,          }
         /* nMaxInstances */ 1,  
         /* nOutBufSize */ 1024,          hp = gethostbyname("localhost");
         /* nInBufSize */ 1024,  
         /* nDefaultWait */ NMPWAIT_USE_DEFAULT_WAIT,          server.sin_family = AF_INET;
         /* lpSecurityAttrib */ NULL);          server.sin_addr = *(struct in_addr *) hp->h_addr;
           server.sin_port = *serverPort;
     if (hnp == INVALID_HANDLE_VALUE && GetLastError() == ERROR_CALL_NOT_IMPLEMENTED) {  
         /* Is this the right way to notify user of skipped tests? */          // connect to server
         ok(hnp == INVALID_HANDLE_VALUE && GetLastError() == ERROR_CALL_NOT_IMPLEMENTED,          connectError = connect(sock, (struct sockaddr *)&server, sizeof(struct sockaddr));
             "CreateNamedPipe not supported on this platform, skipping tests.\n");          ok( !connectError , "client cannot connect to host\n");
         return;          if(connectError) {
     }                  WSACleanup();
     ok(hnp == INVALID_HANDLE_VALUE && GetLastError() == ERROR_INVALID_NAME,                  exit(0);
         "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");          // start receiving data from server
           while( totCharsReceived < TEST_DATA_SIZE ) {
                   numCharsReceived = recv(sock, buf, 1000, 0);
                   ok( numCharsReceived > 0, "socket was closed unexpectedly\n" );
  
     trace("test_CreateNamedPipe returning\n");                  // check received data againt global test data
                   memSame = ! memcmp(buf,gTestData+totCharsReceived,numCharsReceived);
                   ok( memSame, "data integrity lost during transfer\n" );
                   totCharsReceived += numCharsReceived;
           }
 } }
  
 void test_CreateNamedPipe_instances_must_match(void)  static int BlockingServer_Init(int type, SOCKET *sock, SOCKADDR_IN *addr)
 { {
     HANDLE hnp, hnp2;          // BlockingServer_Init creates socket sock of type type and returns assigned port number in addr.
           // returns server port number
  
     /* Check no mismatch */          SOCKADDR_IN tmpAddr;
     hnp = CreateNamedPipe(PIPENAME, PIPE_ACCESS_DUPLEX, PIPE_TYPE_BYTE | PIPE_WAIT,          int bindOK;
         /* nMaxInstances */ 2,          int listenReturn;
         /* nOutBufSize */ 1024,  
         /* nInBufSize */ 1024,          // create socket
         /* nDefaultWait */ NMPWAIT_USE_DEFAULT_WAIT,          *sock = socket(AF_INET, type, 0);
         /* lpSecurityAttrib */ NULL);          ok( *sock != INVALID_SOCKET , "Error in socket()\n");
     ok(hnp != INVALID_HANDLE_VALUE, "CreateNamedPipe failed\n");          if (*sock == INVALID_SOCKET) {
                   WSACleanup();
     hnp2 = CreateNamedPipe(PIPENAME, PIPE_ACCESS_DUPLEX, PIPE_TYPE_BYTE | PIPE_WAIT,                  exit(0);
         /* 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");  
   
     /* etc, etc */  
 }  
   
 /** implementation of alarm() */  
 static DWORD CALLBACK alarmThreadMain(LPVOID arg)  
 {  
     DWORD timeout = (DWORD) arg;  
     trace("alarmThreadMain\n");  
     if (WaitForSingleObject( alarm_event, timeout ) == WAIT_TIMEOUT)  
     {  
         ok(FALSE, "alarm\n");  
         ExitProcess(1);  
     }  
     return 1;  
 }  
   
 HANDLE hnp = INVALID_HANDLE_VALUE;  
   
 /** Trivial byte echo server - disconnects after each session */  
 static DWORD CALLBACK serverThreadMain1(LPVOID arg)  
 {  
     int i;  
   
     trace("serverThreadMain1 start\n");  
     /* Set up a simple echo server */  
     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 */  
 static DWORD CALLBACK serverThreadMain2(LPVOID arg)  
 {  
     int i;  
     HANDLE hnpNext = 0;  
   
     trace("serverThreadMain2\n");  
     /* Set up a simple echo server */  
     hnp = 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(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");  
         hnp = hnpNext;  
     }  
     return 0;  
 }  
   
 /** Trivial byte echo server - uses overlapped named pipe calls */  
 static DWORD CALLBACK serverThreadMain3(LPVOID arg)  
 {  
     int i;  
     HANDLE hEvent;  
   
     trace("serverThreadMain3\n");  
     /* Set up a simple echo server */  
     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)  
 {  
     int i;  
   
     trace("exercizeServer starting\n");  
     for (i = 0; i < NB_SERVER_LOOPS; i++) {  
         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)  
 {  
     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 */          addr->sin_family = AF_INET;
     serverThread = CreateThread(NULL, 0, serverThreadMain1, (void *)8, 0, &serverThreadId);          addr->sin_addr.s_addr = INADDR_ANY;
     ok(serverThread != INVALID_HANDLE_VALUE, "CreateThread\n");          addr->sin_port = htons(0);
     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 */  
     {  
     /* Try server #3 */  
     serverThread = CreateThread(NULL, 0, serverThreadMain3, 0, 0, &serverThreadId);  
     ok(serverThread != INVALID_HANDLE_VALUE, "CreateThread\n");  
     exercizeServer(PIPENAME "serverThreadMain3", serverThread);  
     }  
   
     ok(SetEvent( alarm_event ), "SetEvent\n");  
     CloseHandle( alarm_event );  
     trace("test_NamedPipe_2 returning\n");  
 }  
   
 static void test_DisconnectNamedPipe(void)  
 {  
     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);          // bind socket to port
     ok(hFile != INVALID_HANDLE_VALUE, "CreateFile failed\n");          bindOK = !bind(*sock, (const SOCKADDR *) addr, sizeofSOCKADDR_IN);
           ok( bindOK , "Error binding client to socket\n");
           if( !bindOK ) {
                   WSACleanup();
                   exit(0);
           }
  
     /* don't try to do i/o if one side couldn't be opened, as it hangs */          // get port number
     if (hFile != INVALID_HANDLE_VALUE) {          getsockname(*sock, (SOCKADDR *) &tmpAddr, &sizeofSOCKADDR_IN);
           addr->sin_port = tmpAddr.sin_port;
  
         /* see what happens if server calls DisconnectNamedPipe          // listen on port
          * when there are bytes in the pipe          listenReturn = listen(*sock, NUM_CLIENTS);
          */          ok(listenReturn != SOCKET_ERROR, "error listening on socket\n");
   
           return addr->sin_port;
   }
   
   static void BlockingServer(SOCKET *sock) // listens for incoming connections and accepts up to NUM_CLIENTS connections at once
   {
           struct BlockingServerConnection *connections[NUM_CLIENTS];
           int connIndex = 0;
           SOCKET tmpSock;
           SOCKADDR_IN tmpSockAddr;
   
           // we require one connection from each client thread
           for (connIndex = 0; connIndex < NUM_CLIENTS; connIndex++) {
                           // accept connection
                           tmpSock = accept(*sock, (SOCKADDR *) &tmpSockAddr, &sizeofSOCKADDR_IN);
                           ok(tmpSock != INVALID_SOCKET, "error accepting socket\n");
   
                           // handle new connection
                           connections[connIndex] = BlockingServerConnection_New(tmpSock, tmpSockAddr);
           }
   
           // clean up connections
           for(connIndex = 0; connIndex < NUM_CLIENTS; connIndex++) {
                   BlockingServerConnection_Delete(connections[connIndex]);
           }
   }
   
   static struct BlockingServerConnection * BlockingServerConnection_New(SOCKET sock, SOCKADDR_IN clientAddr)
   {
           struct BlockingServerConnection *connection;
           connection = malloc(sizeof(struct BlockingServerConnection));
           memset(connection, 0, sizeof(struct BlockingServerConnection));
   
           connection->connectedSocket = sock;
           connection->clientAddr = clientAddr;
  
         ok(WriteFile(hFile, obuf, sizeof(obuf), &written, NULL), "WriteFile\n");          // spawn thread to handle sending data
         ok(written == sizeof(obuf), "write file len\n");          connection->serverThread.Handle = CreateThread(NULL, 0, (LPTHREAD_START_ROUTINE) &BlockingServerConnection_Run, connection, 0, &connection->serverThread.ID);
         ok(DisconnectNamedPipe(hnp), "DisconnectNamedPipe while messages waiting\n");  
         ok(WriteFile(hFile, obuf, sizeof(obuf), &written, NULL) == 0          return connection;
             && GetLastError() == ERROR_PIPE_NOT_CONNECTED, "WriteFile to disconnected pipe\n");  }
         ok(ReadFile(hnp, ibuf, sizeof(ibuf), &readden, NULL) == 0  
             && GetLastError() == ERROR_PIPE_NOT_CONNECTED,  static void BlockingServerConnection_Run(struct BlockingServerConnection *connection)
             "ReadFile from disconnected pipe with bytes waiting\n");  {
         ok(CloseHandle(hFile), "CloseHandle\n");          // 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;
   
           // loop and send data
           while( totCharsSent < TEST_DATA_SIZE ) {
                   numCharsSent = send(connection->connectedSocket, gTestData+totCharsSent, (totCharsSent + charsPerSend <= TEST_DATA_SIZE) ? charsPerSend : TEST_DATA_SIZE - totCharsSent, 0);
                   ok( numCharsSent != SOCKET_ERROR, "socket error\n" );
   
                   // pass if send buffer is full
                   if(numCharsSent == 0) {
                           Sleep(100);
                   }
   
                   totCharsSent += numCharsSent;
           }
   
           bClosed = !closesocket(connection->connectedSocket);
           ok(bClosed,"Error closing socket\n");
   }
   
   static void BlockingServerConnection_Delete(struct BlockingServerConnection *c)
   {
           // wait for client to receive data before cleaning up
           WaitForSingleObject(c->serverThread.Handle, INFINITE);
   
           free(c);
   }
   
   static void test_ClientServerBlocking_1(void)
   {
           struct ThreadInfo serverThread;
           struct ThreadInfo *clientThreads;
           DWORD waitStatus;
           SOCKET sock;
           SOCKADDR_IN server;
           int serverPort;
           int threadIndex = 0;
   
           // 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" );
   
           // wait for all clients to receive data before cleaning up
           for(threadIndex = 0; threadIndex < NUM_CLIENTS; threadIndex++) {
                   WaitForSingleObject(clientThreads[threadIndex].Handle, INFINITE);
           }
   
           free(clientThreads);
   }
   
   static void test_Startup(void)
   {
           // initialize application
           WSADATA wsaData;
           int wsastartup_result;
           int versionOK;
   
           // check for compatible winsock version
           wsastartup_result = WSAStartup(MAKEWORD(1,1), &wsaData);
           versionOK = (LOBYTE(wsaData.wVersion) == 1) && (HIBYTE(wsaData.wVersion) == 1);
   
           ok( versionOK , "WSAStartup returns an incompatible sockets version\n");
           if ( !versionOK ) {
                   WSACleanup();
                   exit(0);
           }
   
           ok((wsastartup_result == NO_ERROR), "Error in WSAStartup()\n");
           trace("startup ok\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);
     trace("all tests done\n");          test_Cleanup();
   
           trace("all " __FILE__ " tests done\n");
   
           free(gTestData);
 } }


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

Rizwan Kassim
Powered by
ViewCVS 0.9.2