- added RECT support to the texture upload code
[wine] / dlls / winsock / tests / sock.c
1 /*
2  * Unit test suite for winsock functions
3  *
4  * Copyright 2002 Martin Wilck
5  *
6  * This library is free software; you can redistribute it and/or
7  * modify it under the terms of the GNU Lesser General Public
8  * License as published by the Free Software Foundation; either
9  * version 2.1 of the License, or (at your option) any later version.
10  *
11  * This library is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
14  * Lesser General Public License for more details.
15  *
16  * You should have received a copy of the GNU Lesser General Public
17  * License along with this library; if not, write to the Free Software
18  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
19  */
20
21 #include <winsock2.h>
22 #include <mswsock.h>
23 #include "wine/test.h"
24 #include <winbase.h>
25 #include <winnt.h>
26 #include <winerror.h>
27
28 #define MAX_CLIENTS 4      /* Max number of clients */
29 #define NUM_TESTS   2      /* Number of tests performed */
30 #define FIRST_CHAR 'A'     /* First character in transferred pattern */
31 #define BIND_SLEEP 10      /* seconds to wait between attempts to bind() */
32 #define BIND_TRIES 6       /* Number of bind() attempts */
33 #define TEST_TIMEOUT 30    /* seconds to wait before killing child threads
34                               after server initialization, if something hangs */
35
36 #define wsa_ok(op, cond, msg) \
37    do { \
38         int tmp, err = 0; \
39         tmp = op; \
40         if ( !(cond tmp) ) err = WSAGetLastError(); \
41         ok ( cond tmp, msg, GetCurrentThreadId(), err); \
42    } while (0);
43
44
45 /**************** Structs and typedefs ***************/
46
47 typedef struct thread_info
48 {
49     HANDLE thread;
50     DWORD id;
51 } thread_info;
52
53 /* Information in the server about open client connections */
54 typedef struct sock_info
55 {
56     SOCKET                 s;
57     struct sockaddr_in     addr;
58     struct sockaddr_in     peer;
59     char                  *buf;
60     int                    nread;
61 } sock_info;
62
63 /* Test parameters for both server & client */
64 typedef struct test_params
65 {
66     int          sock_type;
67     int          sock_prot;
68     char        *inet_addr;
69     short        inet_port;
70     int          chunk_size;
71     int          n_chunks;
72     int          n_clients;
73 } test_params;
74
75 /* server-specific test parameters */
76 typedef struct server_params
77 {
78     test_params   *general;
79     DWORD          sock_flags;
80     int            buflen;
81 } server_params;
82
83 /* client-specific test parameters */
84 typedef struct client_params
85 {
86     test_params   *general;
87     DWORD          sock_flags;
88     int            buflen;
89 } client_params;
90
91 /* This type combines all information for setting up a test scenario */
92 typedef struct test_setup
93 {
94     test_params              general;
95     LPVOID                   srv;
96     server_params            srv_params;
97     LPVOID                   clt;
98     client_params            clt_params;
99 } test_setup;
100
101 /* Thread local storage for server */
102 typedef struct server_memory
103 {
104     SOCKET                  s;
105     struct sockaddr_in      addr;
106     sock_info               sock[MAX_CLIENTS];
107 } server_memory;
108
109 /* Thread local storage for client */
110 typedef struct client_memory
111 {
112     SOCKET s;
113     struct sockaddr_in      addr;
114     char                   *send_buf;
115     char                   *recv_buf;
116 } client_memory;
117
118 /**************** Static variables ***************/
119
120 static DWORD      tls;              /* Thread local storage index */
121 static HANDLE     thread[1+MAX_CLIENTS];
122 static DWORD      thread_id[1+MAX_CLIENTS];
123 static HANDLE     server_ready;
124 static HANDLE     client_ready[MAX_CLIENTS];
125 static int        client_id;
126
127 /**************** General utility functions ***************/
128
129 static void set_so_opentype ( BOOL overlapped )
130 {
131     int optval = !overlapped, newval, len = sizeof (int);
132
133     ok ( setsockopt ( INVALID_SOCKET, SOL_SOCKET, SO_OPENTYPE,
134                       (LPVOID) &optval, sizeof (optval) ) == 0,
135          "setting SO_OPENTYPE failed" );
136     ok ( getsockopt ( INVALID_SOCKET, SOL_SOCKET, SO_OPENTYPE,
137                       (LPVOID) &newval, &len ) == 0,
138          "getting SO_OPENTYPE failed" );
139     ok ( optval == newval, "failed to set SO_OPENTYPE" );
140 }
141
142 static int set_blocking ( SOCKET s, BOOL blocking )
143 {
144     u_long val = !blocking;
145     return ioctlsocket ( s, FIONBIO, &val );
146 }
147
148 static void fill_buffer ( char *buf, int chunk_size, int n_chunks )
149 {
150     char c, *p;
151     for ( c = FIRST_CHAR, p = buf; c < FIRST_CHAR + n_chunks; c++, p += chunk_size )
152         memset ( p, c, chunk_size );
153 }
154
155 static char* test_buffer ( char *buf, int chunk_size, int n_chunks )
156 {
157     char c, *p;
158     int i;
159     for ( c = FIRST_CHAR, p = buf; c < FIRST_CHAR + n_chunks; c++, p += chunk_size )
160     {
161         for ( i = 0; i < chunk_size; i++ )
162             if ( p[i] != c ) return p + i;
163     }
164     return NULL;
165 }
166
167 /*
168  * This routine is called when a client / server does not expect any more data,
169  * but needs to acknowedge the closing of the connection (by reasing 0 bytes).
170  */
171 static void read_zero_bytes ( SOCKET s )
172 {
173     char buf[256];
174     int tmp, n = 0;
175     while ( ( tmp = recv ( s, buf, 256, 0 ) ) > 0 )
176         n += tmp;
177     ok ( n <= 0, "garbage data received: %d bytes\n", n );
178 }
179
180 static int do_synchronous_send ( SOCKET s, char *buf, int buflen, int sendlen )
181 {
182     char* last = buf + buflen, *p;
183     int n = 1;
184     for ( p = buf; n > 0 && p < last; p += n )
185         n = send ( s, p, min ( sendlen, last - p ), 0 );
186     wsa_ok ( n, 0 <=, "do_synchronous_send (%lx): error %d" );
187     return p - buf;
188 }
189
190 static int do_synchronous_recv ( SOCKET s, char *buf, int buflen, int recvlen )
191 {
192     char* last = buf + buflen, *p;
193     int n = 1;
194     for ( p = buf; n > 0 && p < last; p += n )
195         n = recv ( s, p, min ( recvlen, last - p ), 0 );
196     wsa_ok ( n, 0 <=, "do_synchronous_recv (%lx): error %d:" );
197     return p - buf;
198 }
199
200 /*
201  *  Call this routine right after thread startup.
202  *  SO_OPENTYPE must by 0, regardless what the server did.
203  */
204 static void check_so_opentype (void)
205 {
206     int tmp = 1, len;
207     len = sizeof (tmp);
208     getsockopt ( INVALID_SOCKET, SOL_SOCKET, SO_OPENTYPE, (LPVOID) &tmp, &len );
209     ok ( tmp == 0, "check_so_opentype: wrong startup value of SO_OPENTYPE: %d", tmp );
210 }
211
212 /**************** Server utility functions ***************/
213
214 /*
215  *  Even if we have closed our server socket cleanly,
216  *  the OS may mark the address "in use" for some time -
217  *  this happens with native Linux apps, too.
218  */
219 static void do_bind ( SOCKET s, struct sockaddr* addr, int addrlen )
220 {
221     int err, wsaerr = 0, n_try = BIND_TRIES;
222
223     while ( ( err = bind ( s, addr, addrlen ) ) != 0 &&
224             ( wsaerr = WSAGetLastError () ) == WSAEADDRINUSE &&
225             n_try-- >= 0)
226     {
227         trace ( "address in use, waiting ...\n" );
228         Sleep ( 1000 * BIND_SLEEP );
229     }
230     ok ( err == 0, "failed to bind: %d\n", wsaerr );
231 }
232
233 static void server_start ( server_params *par )
234 {
235     int i;
236     test_params *gen = par->general;
237     server_memory *mem = (LPVOID) LocalAlloc ( LPTR, sizeof (server_memory));
238
239     TlsSetValue ( tls, mem );
240     mem->s = WSASocketA ( AF_INET, gen->sock_type, gen->sock_prot,
241                           NULL, 0, par->sock_flags );
242     ok ( mem->s != INVALID_SOCKET, "Server: WSASocket failed" );
243
244     mem->addr.sin_family = AF_INET;
245     mem->addr.sin_addr.s_addr = inet_addr ( gen->inet_addr );
246     mem->addr.sin_port = htons ( gen->inet_port );
247
248     for (i = 0; i < MAX_CLIENTS; i++)
249     {
250         mem->sock[i].s = INVALID_SOCKET;
251         mem->sock[i].buf = (LPVOID) LocalAlloc ( LPTR, gen->n_chunks * gen->chunk_size );
252         mem->sock[i].nread = 0;
253     }
254
255     if ( gen->sock_type == SOCK_STREAM )
256         do_bind ( mem->s, (struct sockaddr*) &mem->addr, sizeof (mem->addr) );
257 }
258
259 static void server_stop (void)
260 {
261     int i;
262     server_memory *mem = TlsGetValue ( tls );
263
264     for (i = 0; i < MAX_CLIENTS; i++ )
265     {
266         LocalFree ( (HANDLE) mem->sock[i].buf );
267         if ( mem->sock[i].s != INVALID_SOCKET )
268             closesocket ( mem->sock[i].s );
269     }
270     ok ( closesocket ( mem->s ) == 0, "closesocket failed" );
271     LocalFree ( (HANDLE) mem );
272     ExitThread ( GetCurrentThreadId () );
273 }
274
275 /**************** Client utilitiy functions ***************/
276
277 static void client_start ( client_params *par )
278 {
279     test_params *gen = par->general;
280     client_memory *mem = (LPVOID) LocalAlloc (LPTR, sizeof (client_memory));
281
282     TlsSetValue ( tls, mem );
283
284     WaitForSingleObject ( server_ready, INFINITE );
285
286     mem->s = WSASocketA ( AF_INET, gen->sock_type, gen->sock_prot,
287                           NULL, 0, par->sock_flags );
288
289     mem->addr.sin_family = AF_INET;
290     mem->addr.sin_addr.s_addr = inet_addr ( gen->inet_addr );
291     mem->addr.sin_port = htons ( gen->inet_port );
292
293     ok ( mem->s != INVALID_SOCKET, "Client: WSASocket failed" );
294
295     mem->send_buf = (LPVOID) LocalAlloc ( LPTR, 2 * gen->n_chunks * gen->chunk_size );
296     mem->recv_buf = mem->send_buf + gen->n_chunks * gen->chunk_size;
297     fill_buffer ( mem->send_buf, gen->chunk_size, gen->n_chunks );
298
299     SetEvent ( client_ready[client_id] );
300     /* Wait for the other clients to come up */
301     WaitForMultipleObjects ( min ( gen->n_clients, MAX_CLIENTS ), client_ready, TRUE, INFINITE );
302 }
303
304 static void client_stop (void)
305 {
306     client_memory *mem = TlsGetValue ( tls );
307     wsa_ok ( closesocket ( mem->s ), 0 ==, "closesocket error (%lx): %d\n" );
308     LocalFree ( (HANDLE) mem->send_buf );
309     LocalFree ( (HANDLE) mem );
310     ExitThread(0);
311 }
312
313 /**************** Servers ***************/
314
315 /*
316  * simple_server: A very basic server doing synchronous IO.
317  */
318 static VOID WINAPI simple_server ( server_params *par )
319 {
320     test_params *gen = par->general;
321     server_memory *mem;
322     int n_recvd, n_sent, n_expected = gen->n_chunks * gen->chunk_size, tmp, i,
323         id = GetCurrentThreadId();
324     char *p;
325
326     trace ( "simple_server (%x) starting\n", id );
327
328     set_so_opentype ( FALSE ); /* non-overlapped */
329     server_start ( par );
330     mem = TlsGetValue ( tls );
331
332     wsa_ok ( set_blocking ( mem->s, TRUE ), 0 ==, "simple_server (%lx): failed to set blocking mode: %d");
333     wsa_ok ( listen ( mem->s, SOMAXCONN ), 0 ==, "simple_server (%lx): listen failed: %d");
334
335     trace ( "simple_server (%x) ready\n", id );
336     SetEvent ( server_ready ); /* notify clients */
337
338     for ( i = 0; i < min ( gen->n_clients, MAX_CLIENTS ); i++ )
339     {
340         trace ( "simple_server (%x): waiting for client\n", id );
341
342         /* accept a single connection */
343         tmp = sizeof ( mem->sock[0].peer );
344         mem->sock[0].s = accept ( mem->s, (struct sockaddr*) &mem->sock[0].peer, &tmp );
345         wsa_ok ( mem->sock[0].s, INVALID_SOCKET !=, "simple_server (%lx): accept failed: %d" );
346
347         ok ( mem->sock[0].peer.sin_addr.s_addr == inet_addr ( gen->inet_addr ),
348              "simple_server (%x): strange peer address", id );
349
350         /* Receive data & check it */
351         n_recvd = do_synchronous_recv ( mem->sock[0].s, mem->sock[0].buf, n_expected, par->buflen );
352         ok ( n_recvd == n_expected,
353              "simple_server (%x): received less data then expected: %d of %d", id, n_recvd, n_expected );
354         p = test_buffer ( mem->sock[0].buf, gen->chunk_size, gen->n_chunks );
355         ok ( p == NULL, "simple_server (%x): test pattern error: %d", id, p - mem->sock[0].buf);
356
357         /* Echo data back */
358         n_sent = do_synchronous_send ( mem->sock[0].s, mem->sock[0].buf, n_expected, par->buflen );
359         ok ( n_sent == n_expected,
360              "simple_server (%x): sent less data then expected: %d of %d", id, n_sent, n_expected );
361
362         /* cleanup */
363         read_zero_bytes ( mem->sock[0].s );
364         wsa_ok ( closesocket ( mem->sock[0].s ),  0 ==, "simple_server (%lx): closesocket error: %d" );
365         mem->sock[0].s = INVALID_SOCKET;
366     }
367
368     trace ( "simple_server (%x) exiting\n", id );
369     server_stop ();
370 }
371
372 /**************** Clients ***************/
373
374 /*
375  * simple_client: A very basic client doing synchronous IO.
376  */
377 static VOID WINAPI simple_client ( client_params *par )
378 {
379     test_params *gen = par->general;
380     client_memory *mem;
381     int n_sent, n_recvd, n_expected = gen->n_chunks * gen->chunk_size, id;
382     char *p;
383
384     id = GetCurrentThreadId();
385     trace ( "simple_client (%x): starting\n", id );
386     /* wait here because we want to call set_so_opentype before creating a socket */
387     WaitForSingleObject ( server_ready, INFINITE );
388     trace ( "simple_client (%x): server ready\n", id );
389
390     check_so_opentype ();
391     set_so_opentype ( FALSE ); /* non-overlapped */
392     client_start ( par );
393     mem = TlsGetValue ( tls );
394
395     /* Connect */
396     wsa_ok ( connect ( mem->s, (struct sockaddr*) &mem->addr, sizeof ( mem->addr ) ),
397              0 ==, "simple_client (%lx): connect error: %d" );
398     ok ( set_blocking ( mem->s, TRUE ) == 0,
399          "simple_client (%x): failed to set blocking mode", id );
400     trace ( "simple_client (%x) connected\n", id );
401
402     /* send data to server */
403     n_sent = do_synchronous_send ( mem->s, mem->send_buf, n_expected, par->buflen );
404     ok ( n_sent == n_expected,
405          "simple_client (%x): sent less data then expected: %d of %d", id, n_sent, n_expected );
406
407     /* shutdown send direction */
408     wsa_ok ( shutdown ( mem->s, SD_SEND ), 0 ==, "simple_client (%lx): shutdown failed: %d" );
409
410     /* Receive data echoed back & check it */
411     n_recvd = do_synchronous_recv ( mem->s, mem->recv_buf, n_expected, par->buflen );
412     ok ( n_recvd == n_expected,
413          "simple_client (%x): received less data then expected: %d of %d", id, n_recvd, n_expected );
414
415     /* check data */
416     p = test_buffer ( mem->recv_buf, gen->chunk_size, gen->n_chunks );
417     ok ( p == NULL, "simple_client (%x): test pattern error: %d", id, p - mem->recv_buf);
418
419     /* cleanup */
420     read_zero_bytes ( mem->s );
421     trace ( "simple_client (%x) exiting\n", id );
422     client_stop ();
423 }
424
425 /*
426  * event_client: An event-driven client
427  */
428 static void WINAPI event_client ( client_params *par )
429 {
430     test_params *gen = par->general;
431     client_memory *mem;
432     int id = GetCurrentThreadId(), n_expected = gen->n_chunks * gen->chunk_size,
433         tmp, err, n;
434     HANDLE event;
435     WSANETWORKEVENTS wsa_events;
436     char *send_last, *recv_last, *send_p, *recv_p;
437     long mask = FD_READ | FD_WRITE | FD_CLOSE;
438
439     trace ( "event_client (%x): starting\n", id );
440     client_start ( par );
441     trace ( "event_client (%x): server ready\n", id );
442
443     mem = TlsGetValue ( tls );
444
445     /* Prepare event notification for connect, makes socket nonblocking */
446     event = WSACreateEvent ();
447     WSAEventSelect ( mem->s, event, FD_CONNECT );
448     tmp = connect ( mem->s, (struct sockaddr*) &mem->addr, sizeof ( mem->addr ) );
449     if ( tmp != 0 && ( err = WSAGetLastError () ) != WSAEWOULDBLOCK )
450         ok ( 0, "event_client (%x): connect error: %d", id, err );
451
452     tmp = WaitForSingleObject ( event, INFINITE );
453     ok ( tmp == WAIT_OBJECT_0, "event_client (%x): wait for connect event failed: %d", id, tmp );
454     err = WSAEnumNetworkEvents ( mem->s, event, &wsa_events );
455     wsa_ok ( err, 0 ==, "event_client (%lx): WSAEnumNetworkEvents error: %d\n" );
456
457     err = wsa_events.iErrorCode[ FD_CONNECT_BIT ];
458     ok ( err == 0, "event_client (%x): connect error: %d", id, err );
459     if ( err ) goto out;
460
461     trace ( "event_client (%x) connected\n", id );
462
463     WSAEventSelect ( mem->s, event, mask );
464
465     recv_p = mem->recv_buf;
466     recv_last = mem->recv_buf + n_expected;
467     send_p = mem->send_buf;
468     send_last = mem->send_buf + n_expected;
469
470     while ( TRUE )
471     {
472         err = WaitForSingleObject ( event, INFINITE );
473         ok ( err == WAIT_OBJECT_0, "event_client (%x): wait failed", id );
474
475         err = WSAEnumNetworkEvents ( mem->s, event, &wsa_events );
476         wsa_ok ( err, 0 ==, "event_client (%lx): WSAEnumNetworkEvents error: %d\n" );
477
478         if ( wsa_events.lNetworkEvents & FD_WRITE )
479         {
480             err = wsa_events.iErrorCode[ FD_WRITE_BIT ];
481             ok ( err == 0, "event_client (%x): FD_WRITE error code: %d\n", id, err );
482
483             if ( err== 0 )
484                 do
485                 {
486                     n = send ( mem->s, send_p, min ( send_last - send_p, par->buflen ), 0 );
487                     if ( n < 0 )
488                     {
489                         err = WSAGetLastError ();
490                         ok ( err == WSAEWOULDBLOCK, "event_client (%x): send error: %d\n", id, err );
491                     }
492                     else
493                         send_p += n;
494                 }
495                 while ( n >= 0 && send_p < send_last );
496
497             if ( send_p == send_last )
498             {
499                 trace ( "event_client (%x): all data sent - shutdown\n", id );
500                 shutdown ( mem->s, SD_SEND );
501                 mask &= ~FD_WRITE;
502                 WSAEventSelect ( mem->s, event, mask );
503             }
504         }
505         if ( wsa_events.lNetworkEvents & FD_READ )
506         {
507             err = wsa_events.iErrorCode[ FD_READ_BIT ];
508             ok ( err == 0, "event_client (%x): FD_READ error code: %d\n", id, err );
509             if ( err != 0 ) break;
510             
511             /* First read must succeed */
512             n = recv ( mem->s, recv_p, min ( recv_last - recv_p, par->buflen ), 0 );
513             wsa_ok ( n, 0 <=, "event_client (%lx): recv error: %d\n" );
514
515             while ( n >= 0 ) {
516                 recv_p += n;
517                 if ( recv_p == recv_last )
518                 {
519                     mask &= ~FD_READ;
520                     trace ( "event_client (%x): all data received\n", id );
521                     WSAEventSelect ( mem->s, event, mask );
522                     break;
523                 }
524                 n = recv ( mem->s, recv_p, min ( recv_last - recv_p, par->buflen ), 0 );
525                 if ( n < 0 && ( err = WSAGetLastError()) != WSAEWOULDBLOCK )
526                     ok ( 0, "event_client (%x): read error: %d\n", id, err );
527                 
528             }
529         }   
530         if ( wsa_events.lNetworkEvents & FD_CLOSE )
531         {
532             trace ( "event_client (%x): close event\n", id );
533             err = wsa_events.iErrorCode[ FD_CLOSE_BIT ];
534             ok ( err == 0, "event_client (%x): FD_CLOSE error code: %d\n", id, err );
535             break;
536         }
537     }
538
539     ok ( send_p == send_last,
540          "simple_client (%x): sent less data then expected: %d of %d",
541          id, send_p - mem->send_buf, n_expected );
542     ok ( recv_p == recv_last,
543          "simple_client (%x): received less data then expected: %d of %d",
544          id, recv_p - mem->recv_buf, n_expected );
545     recv_p = test_buffer ( mem->recv_buf, gen->chunk_size, gen->n_chunks );
546     ok ( recv_p == NULL, "event_client (%x): test pattern error: %d", id, recv_p - mem->recv_buf);
547
548 out:
549     WSACloseEvent ( event );
550     trace ( "event_client (%x) exiting\n", id );
551     client_stop ();
552 }
553
554 /**************** Main program utility functions ***************/
555
556 static void Init (void)
557 {
558     WORD ver = MAKEWORD (2, 2);
559     WSADATA data;
560
561     ok ( WSAStartup ( ver, &data ) == 0, "WSAStartup failed" );
562     tls = TlsAlloc();
563 }
564
565 static void Exit (void)
566 {
567     TlsFree ( tls );
568     ok ( WSACleanup() == 0, "WSACleanup failed" );
569 }
570
571 static void StartServer (LPTHREAD_START_ROUTINE routine,
572                          test_params *general, server_params *par)
573 {
574     par->general = general;
575     thread[0] = CreateThread ( NULL, 0, routine, par, 0, &thread_id[0] );
576     ok ( thread[0] != NULL, "Failed to create server thread" );
577 }
578
579 static void StartClients (LPTHREAD_START_ROUTINE routine,
580                           test_params *general, client_params *par)
581 {
582     int i;
583     par->general = general;
584     for ( i = 1; i <= min ( general->n_clients, MAX_CLIENTS ); i++ )
585     {
586         client_id = i - 1;
587         thread[i] = CreateThread ( NULL, 0, routine, par, 0, &thread_id[i] );
588         ok ( thread[i] != NULL, "Failed to create client thread" );
589         /* Make sure the client is up and running */
590         WaitForSingleObject ( client_ready[client_id], INFINITE );
591     };
592 }
593
594 static void do_test( test_setup *test )
595 {
596     DWORD i, n = min (test->general.n_clients, MAX_CLIENTS);
597     DWORD wait;
598
599     server_ready = CreateEventA ( NULL, TRUE, FALSE, NULL );
600     for (i = 0; i <= n; i++)
601         client_ready[i] = CreateEventA ( NULL, TRUE, FALSE, NULL );
602
603     StartServer ( test->srv, &test->general, &test->srv_params );
604     StartClients ( test->clt, &test->general, &test->clt_params );
605     WaitForSingleObject ( server_ready, INFINITE );
606
607     wait = WaitForMultipleObjects ( 1 + n, thread, TRUE, 1000 * TEST_TIMEOUT );
608     ok ( wait >= WAIT_OBJECT_0 && wait <= WAIT_OBJECT_0 + n , 
609          "some threads have not completed: %lx\n", wait );
610
611     if ( ! ( wait >= WAIT_OBJECT_0 && wait <= WAIT_OBJECT_0 + n ) )
612     {
613         for (i = 0; i <= n; i++)
614         {
615             trace ("terminating thread %08lx\n", thread_id[i]);
616             if ( WaitForSingleObject ( thread[i], 0 ) != WAIT_OBJECT_0 )
617                 TerminateThread ( thread [i], 0 );
618         }
619     }
620     CloseHandle ( server_ready );
621     for (i = 0; i <= n; i++)
622         CloseHandle ( client_ready[i] );
623 }
624
625 /************* Array containing the tests to run **********/
626
627 #define STD_STREAM_SOCKET \
628             SOCK_STREAM, \
629             0, \
630             "127.0.0.1", \
631             9374
632
633 static test_setup tests [NUM_TESTS] =
634 {
635     /* Test 0: synchronous client and server */
636     {
637         {
638             STD_STREAM_SOCKET,
639             2048,
640             16,
641             2
642         },
643         simple_server,
644         {
645             NULL,
646             0,
647             64
648         },
649         simple_client,
650         {
651             NULL,
652             0,
653             128
654         }
655     },
656     /* Test 1: event-driven client, synchronous server */
657     {
658         {
659             STD_STREAM_SOCKET,
660             2048,
661             16,
662             2
663         },
664         simple_server,
665         {
666             NULL,
667             0,
668             64
669         },
670         event_client,
671         {
672             NULL,
673             WSA_FLAG_OVERLAPPED,
674             128
675         }
676     }
677 };
678
679 /**************** Main program  ***************/
680
681 START_TEST( sock )
682 {
683     int i;
684     Init();
685
686     for (i = 0; i < NUM_TESTS; i++)
687     {
688         trace ( " **** STARTING TEST %d **** \n", i );
689         do_test (  &tests[i] );
690         trace ( " **** TEST %d COMPLETE **** \n", i );
691     }
692
693     Exit();
694 }