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