Skip to content
Projects
Groups
Snippets
Help
This project
Loading...
Sign in / Register
Toggle navigation
W
wine-winehq
Project
Project
Details
Activity
Cycle Analytics
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Charts
Issues
0
Issues
0
List
Board
Labels
Milestones
Merge Requests
0
Merge Requests
0
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Charts
Registry
Registry
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Charts
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
wine
wine-winehq
Commits
b28f933b
Commit
b28f933b
authored
Apr 27, 2002
by
Martin Wilck
Committed by
Alexandre Julliard
Apr 27, 2002
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
Added unit test for winsock.
parent
75242f9b
Hide whitespace changes
Inline
Side-by-side
Showing
4 changed files
with
698 additions
and
0 deletions
+698
-0
Makefile.in
dlls/winsock/Makefile.in
+5
-0
.cvsignore
dlls/winsock/tests/.cvsignore
+3
-0
sock.c
dlls/winsock/tests/sock.c
+683
-0
ws2_32_test.spec
dlls/winsock/tests/ws2_32_test.spec
+7
-0
No files found.
dlls/winsock/Makefile.in
View file @
b28f933b
...
...
@@ -13,6 +13,11 @@ C_SRCS = \
async.c
\
socket.c
CTESTS
=
\
tests/sock.c
EXTRASUBDIRS
=
tests
@MAKE_DLL_RULES@
### Dependencies:
dlls/winsock/tests/.cvsignore
0 → 100644
View file @
b28f933b
sock.ok
testlist.c
ws2_32_test.spec.c
dlls/winsock/tests/sock.c
0 → 100644
View file @
b28f933b
/*
* Unit test suite for winsock functions
*
* Copyright 2002 Martin Wilck
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
#include "wine/test.h"
#include <winbase.h>
#include <winnt.h>
#include <winerror.h>
#undef USE_WS_PREFIX
#include <winsock2.h>
#define MAX_CLIENTS 4
/* Max number of clients */
#define NUM_TESTS 2
/* Number of tests performed */
#define FIRST_CHAR 'A'
/* First character in transferred pattern */
#define BIND_SLEEP 10
/* seconds to wait between attempts to bind() */
#define BIND_TRIES 6
/* Number of bind() attempts */
#define TEST_TIMEOUT 30
/* seconds to wait before killing child threads
after server initialization, if something hangs */
#define wsa_ok(op, cond, msg) \
do { \
int tmp, err = 0; \
tmp = op; \
if ( !(cond tmp) ) err = WSAGetLastError(); \
ok ( cond tmp, msg, GetCurrentThreadId(), err); \
} while (0);
/**************** Structs and typedefs ***************/
typedef
struct
thread_info
{
HANDLE
thread
;
DWORD
id
;
}
thread_info
;
/* Information in the server about open client connections */
typedef
struct
sock_info
{
SOCKET
s
;
struct
sockaddr_in
addr
;
struct
sockaddr_in
peer
;
char
*
buf
;
int
nread
;
}
sock_info
;
/* Test parameters for both server & client */
typedef
struct
test_params
{
int
sock_type
;
int
sock_prot
;
char
*
inet_addr
;
int
inet_port
;
int
chunk_size
;
int
n_chunks
;
int
n_clients
;
}
test_params
;
/* server-specific test parameters */
typedef
struct
server_params
{
test_params
*
general
;
DWORD
sock_flags
;
int
buflen
;
}
server_params
;
/* client-specific test parameters */
typedef
struct
client_params
{
test_params
*
general
;
DWORD
sock_flags
;
int
buflen
;
}
client_params
;
/* This type combines all information for setting up a test scenario */
typedef
struct
test_setup
{
test_params
general
;
LPVOID
srv
;
server_params
srv_params
;
LPVOID
clt
;
client_params
clt_params
;
}
test_setup
;
/* Thread local storage for server */
typedef
struct
server_memory
{
SOCKET
s
;
struct
sockaddr_in
addr
;
sock_info
sock
[
MAX_CLIENTS
];
}
server_memory
;
/* Thread local storage for client */
typedef
struct
client_memory
{
SOCKET
s
;
struct
sockaddr_in
addr
;
char
*
send_buf
;
char
*
recv_buf
;
}
client_memory
;
/**************** Static variables ***************/
static
DWORD
tls
;
/* Thread local storage index */
static
HANDLE
thread
[
1
+
MAX_CLIENTS
];
static
DWORD
thread_id
[
1
+
MAX_CLIENTS
];
static
HANDLE
server_ready
;
static
HANDLE
client_ready
[
MAX_CLIENTS
];
static
int
client_id
;
/**************** General utility functions ***************/
static
void
set_so_opentype
(
BOOL
overlapped
)
{
int
optval
=
!
overlapped
,
newval
,
len
=
sizeof
(
int
);
ok
(
setsockopt
(
INVALID_SOCKET
,
SOL_SOCKET
,
SO_OPENTYPE
,
(
LPVOID
)
&
optval
,
sizeof
(
optval
)
)
==
0
,
"setting SO_OPENTYPE failed"
);
ok
(
getsockopt
(
INVALID_SOCKET
,
SOL_SOCKET
,
SO_OPENTYPE
,
(
LPVOID
)
&
newval
,
&
len
)
==
0
,
"getting SO_OPENTYPE failed"
);
ok
(
optval
==
newval
,
"failed to set SO_OPENTYPE"
);
}
static
int
set_blocking
(
SOCKET
s
,
BOOL
blocking
)
{
u_long
val
=
!
blocking
;
return
ioctlsocket
(
s
,
FIONBIO
,
&
val
);
}
static
void
fill_buffer
(
char
*
buf
,
int
chunk_size
,
int
n_chunks
)
{
char
c
,
*
p
;
for
(
c
=
FIRST_CHAR
,
p
=
buf
;
c
<
FIRST_CHAR
+
n_chunks
;
c
++
,
p
+=
chunk_size
)
memset
(
p
,
c
,
chunk_size
);
}
static
char
*
test_buffer
(
char
*
buf
,
int
chunk_size
,
int
n_chunks
)
{
char
c
,
*
p
;
int
i
;
for
(
c
=
FIRST_CHAR
,
p
=
buf
;
c
<
FIRST_CHAR
+
n_chunks
;
c
++
,
p
+=
chunk_size
)
{
for
(
i
=
0
;
i
<
chunk_size
;
i
++
)
if
(
p
[
i
]
!=
c
)
return
p
+
i
;
}
return
NULL
;
}
/*
* This routine is called when a client / server does not expect any more data,
* but needs to acknowedge the closing of the connection (by reasing 0 bytes).
*/
static
void
read_zero_bytes
(
SOCKET
s
)
{
char
buf
[
256
];
int
tmp
,
n
=
0
;
while
(
(
tmp
=
recv
(
s
,
buf
,
256
,
0
)
)
>
0
)
n
+=
tmp
;
ok
(
n
<=
0
,
"garbage data received: %d bytes
\n
"
,
n
);
}
static
int
do_synchronous_send
(
SOCKET
s
,
char
*
buf
,
int
buflen
,
int
sendlen
)
{
char
*
last
=
buf
+
buflen
,
*
p
;
int
n
=
1
;
for
(
p
=
buf
;
n
>
0
&&
p
<
last
;
p
+=
n
)
n
=
send
(
s
,
p
,
min
(
sendlen
,
last
-
p
),
0
);
wsa_ok
(
n
,
0
<=
,
"do_synchronous_send (%x): error %d"
);
return
p
-
buf
;
}
static
int
do_synchronous_recv
(
SOCKET
s
,
char
*
buf
,
int
buflen
,
int
recvlen
)
{
char
*
last
=
buf
+
buflen
,
*
p
;
int
n
=
1
;
for
(
p
=
buf
;
n
>
0
&&
p
<
last
;
p
+=
n
)
n
=
recv
(
s
,
p
,
min
(
recvlen
,
last
-
p
),
0
);
wsa_ok
(
n
,
0
<=
,
"do_synchronous_recv (%x): error %d:"
);
return
p
-
buf
;
}
/*
* Call this routine right after thread startup.
* SO_OPENTYPE must by 0, regardless what the server did.
*/
static
void
check_so_opentype
(
void
)
{
int
tmp
=
1
,
len
;
len
=
sizeof
(
tmp
);
getsockopt
(
INVALID_SOCKET
,
SOL_SOCKET
,
SO_OPENTYPE
,
(
LPVOID
)
&
tmp
,
&
len
);
ok
(
tmp
==
0
,
"check_so_opentype: wrong startup value of SO_OPENTYPE: %d"
,
tmp
);
}
/**************** Server utility functions ***************/
/*
* Even if we have closed our server socket cleanly,
* the OS may mark the address "in use" for some time -
* this happens with native Linux apps, too.
*/
static
void
do_bind
(
SOCKET
s
,
struct
sockaddr
*
addr
,
int
addrlen
)
{
int
err
,
wsaerr
=
0
,
n_try
=
BIND_TRIES
;
while
(
(
err
=
bind
(
s
,
addr
,
addrlen
)
)
!=
0
&&
(
wsaerr
=
WSAGetLastError
()
)
==
WSAEADDRINUSE
&&
n_try
--
>=
0
)
{
trace
(
"address in use, waiting ...
\n
"
);
Sleep
(
1000
*
BIND_SLEEP
);
}
ok
(
err
==
0
,
"failed to bind: %d
\n
"
,
wsaerr
);
}
static
void
server_start
(
server_params
*
par
)
{
int
i
;
test_params
*
gen
=
par
->
general
;
server_memory
*
mem
=
(
LPVOID
)
LocalAlloc
(
LPTR
,
sizeof
(
server_memory
));
TlsSetValue
(
tls
,
mem
);
mem
->
s
=
WSASocketA
(
AF_INET
,
gen
->
sock_type
,
gen
->
sock_prot
,
NULL
,
0
,
par
->
sock_flags
);
ok
(
mem
->
s
!=
INVALID_SOCKET
,
"Server: WSASocket failed"
);
mem
->
addr
.
sin_family
=
AF_INET
;
mem
->
addr
.
sin_addr
.
s_addr
=
inet_addr
(
gen
->
inet_addr
);
mem
->
addr
.
sin_port
=
htons
(
gen
->
inet_port
);
for
(
i
=
0
;
i
<
MAX_CLIENTS
;
i
++
)
{
mem
->
sock
[
i
].
s
=
INVALID_SOCKET
;
mem
->
sock
[
i
].
buf
=
(
LPVOID
)
LocalAlloc
(
LPTR
,
gen
->
n_chunks
*
gen
->
chunk_size
);
mem
->
sock
[
i
].
nread
=
0
;
}
if
(
gen
->
sock_type
==
SOCK_STREAM
)
do_bind
(
mem
->
s
,
(
struct
sockaddr
*
)
&
mem
->
addr
,
sizeof
(
mem
->
addr
)
);
}
static
void
server_stop
(
void
)
{
int
i
;
server_memory
*
mem
=
TlsGetValue
(
tls
);
for
(
i
=
0
;
i
<
MAX_CLIENTS
;
i
++
)
{
LocalFree
(
(
HANDLE
)
mem
->
sock
[
i
].
buf
);
if
(
mem
->
sock
[
i
].
s
!=
INVALID_SOCKET
)
closesocket
(
mem
->
sock
[
i
].
s
);
}
ok
(
closesocket
(
mem
->
s
)
==
0
,
"closesocket failed"
);
LocalFree
(
(
HANDLE
)
mem
);
ExitThread
(
GetCurrentThreadId
()
);
}
/**************** Client utilitiy functions ***************/
static
void
client_start
(
client_params
*
par
)
{
test_params
*
gen
=
par
->
general
;
client_memory
*
mem
=
(
LPVOID
)
LocalAlloc
(
LPTR
,
sizeof
(
client_memory
));
TlsSetValue
(
tls
,
mem
);
WaitForSingleObject
(
server_ready
,
INFINITE
);
mem
->
s
=
WSASocketA
(
AF_INET
,
gen
->
sock_type
,
gen
->
sock_prot
,
NULL
,
0
,
par
->
sock_flags
);
mem
->
addr
.
sin_family
=
AF_INET
;
mem
->
addr
.
sin_addr
.
s_addr
=
inet_addr
(
gen
->
inet_addr
);
mem
->
addr
.
sin_port
=
htons
(
gen
->
inet_port
);
ok
(
mem
->
s
!=
INVALID_SOCKET
,
"Client: WSASocket failed"
);
mem
->
send_buf
=
(
LPVOID
)
LocalAlloc
(
LPTR
,
2
*
gen
->
n_chunks
*
gen
->
chunk_size
);
mem
->
recv_buf
=
mem
->
send_buf
+
gen
->
n_chunks
*
gen
->
chunk_size
;
fill_buffer
(
mem
->
send_buf
,
gen
->
chunk_size
,
gen
->
n_chunks
);
SetEvent
(
client_ready
[
client_id
]
);
/* Wait for the other clients to come up */
WaitForMultipleObjects
(
min
(
gen
->
n_clients
,
MAX_CLIENTS
),
client_ready
,
TRUE
,
INFINITE
);
}
static
void
client_stop
(
void
)
{
client_memory
*
mem
=
TlsGetValue
(
tls
);
wsa_ok
(
closesocket
(
mem
->
s
),
0
==
,
"closesocket error (%x): %d
\n
"
);
LocalFree
(
(
HANDLE
)
mem
->
send_buf
);
LocalFree
(
(
HANDLE
)
mem
);
ExitThread
(
0
);
}
/**************** Servers ***************/
/*
* simple_server: A very basic server doing synchronous IO.
*/
static
VOID
WINAPI
simple_server
(
server_params
*
par
)
{
test_params
*
gen
=
par
->
general
;
server_memory
*
mem
;
int
n_recvd
,
n_sent
,
n_expected
=
gen
->
n_chunks
*
gen
->
chunk_size
,
tmp
,
i
,
id
=
GetCurrentThreadId
();
char
*
p
;
trace
(
"simple_server (%x) starting
\n
"
,
id
);
set_so_opentype
(
FALSE
);
/* non-overlapped */
server_start
(
par
);
mem
=
TlsGetValue
(
tls
);
wsa_ok
(
set_blocking
(
mem
->
s
,
TRUE
),
0
==
,
"simple_server (%x): failed to set blocking mode: %d"
);
wsa_ok
(
listen
(
mem
->
s
,
SOMAXCONN
),
0
==
,
"simple_server (%x): listen failed: %d"
);
trace
(
"simple_server (%x) ready
\n
"
,
id
);
SetEvent
(
server_ready
);
/* notify clients */
for
(
i
=
0
;
i
<
min
(
gen
->
n_clients
,
MAX_CLIENTS
);
i
++
)
{
trace
(
"simple_server (%x): waiting for client
\n
"
,
id
);
/* accept a single connection */
tmp
=
sizeof
(
mem
->
sock
[
0
].
peer
);
mem
->
sock
[
0
].
s
=
accept
(
mem
->
s
,
(
struct
sockaddr
*
)
&
mem
->
sock
[
0
].
peer
,
&
tmp
);
wsa_ok
(
mem
->
sock
[
0
].
s
,
INVALID_SOCKET
!=
,
"simple_server (%x): accept failed: %d"
);
ok
(
mem
->
sock
[
0
].
peer
.
sin_addr
.
s_addr
==
inet_addr
(
gen
->
inet_addr
),
"simple_server (%x): strange peer address"
,
id
);
/* Receive data & check it */
n_recvd
=
do_synchronous_recv
(
mem
->
sock
[
0
].
s
,
mem
->
sock
[
0
].
buf
,
n_expected
,
par
->
buflen
);
ok
(
n_recvd
==
n_expected
,
"simple_server (%x): received less data then expected: %d of %d"
,
id
,
n_recvd
,
n_expected
);
p
=
test_buffer
(
mem
->
sock
[
0
].
buf
,
gen
->
chunk_size
,
gen
->
n_chunks
);
ok
(
p
==
NULL
,
"simple_server (%x): test pattern error: %d"
,
p
-
mem
->
sock
[
0
].
buf
);
/* Echo data back */
n_sent
=
do_synchronous_send
(
mem
->
sock
[
0
].
s
,
mem
->
sock
[
0
].
buf
,
n_expected
,
par
->
buflen
);
ok
(
n_sent
==
n_expected
,
"simple_server (%x): sent less data then expected: %d of %d"
,
id
,
n_sent
,
n_expected
);
/* cleanup */
read_zero_bytes
(
mem
->
sock
[
0
].
s
);
wsa_ok
(
closesocket
(
mem
->
sock
[
0
].
s
),
0
==
,
"simple_server (%x): closesocket error: %d"
);
mem
->
sock
[
0
].
s
=
INVALID_SOCKET
;
}
trace
(
"simple_server (%x) exiting
\n
"
,
id
);
server_stop
();
}
/**************** Clients ***************/
/*
* simple_client: A very basic client doing synchronous IO.
*/
static
VOID
WINAPI
simple_client
(
client_params
*
par
)
{
test_params
*
gen
=
par
->
general
;
client_memory
*
mem
;
int
n_sent
,
n_recvd
,
n_expected
=
gen
->
n_chunks
*
gen
->
chunk_size
,
id
;
char
*
p
;
id
=
GetCurrentThreadId
();
trace
(
"simple_client (%x): starting
\n
"
,
id
);
/* wait here because we want to call set_so_opentype before creating a socket */
WaitForSingleObject
(
server_ready
,
INFINITE
);
trace
(
"simple_client (%x): server ready
\n
"
,
id
);
check_so_opentype
();
set_so_opentype
(
FALSE
);
/* non-overlapped */
client_start
(
par
);
mem
=
TlsGetValue
(
tls
);
/* Connect */
wsa_ok
(
connect
(
mem
->
s
,
(
struct
sockaddr
*
)
&
mem
->
addr
,
sizeof
(
mem
->
addr
)
),
0
==
,
"simple_client (%x): connect error: %d"
);
ok
(
set_blocking
(
mem
->
s
,
TRUE
)
==
0
,
"simple_client (%x): failed to set blocking mode"
,
id
);
trace
(
"simple_client (%x) connected
\n
"
,
id
);
/* send data to server */
n_sent
=
do_synchronous_send
(
mem
->
s
,
mem
->
send_buf
,
n_expected
,
par
->
buflen
);
ok
(
n_sent
==
n_expected
,
"simple_client (%x): sent less data then expected: %d of %d"
,
id
,
n_sent
,
n_expected
);
/* shutdown send direction */
wsa_ok
(
shutdown
(
mem
->
s
,
SD_SEND
),
0
==
,
"simple_client (%x): shutdown failed: %d"
);
/* Receive data echoed back & check it */
n_recvd
=
do_synchronous_recv
(
mem
->
s
,
mem
->
recv_buf
,
n_expected
,
par
->
buflen
);
ok
(
n_recvd
==
n_expected
,
"simple_client (%x): received less data then expected: %d of %d"
,
id
,
n_recvd
,
n_expected
);
/* check data */
p
=
test_buffer
(
mem
->
recv_buf
,
gen
->
chunk_size
,
gen
->
n_chunks
);
ok
(
p
==
NULL
,
"simple_client (%x): test pattern error: %d"
,
id
,
p
-
mem
->
recv_buf
);
/* cleanup */
read_zero_bytes
(
mem
->
s
);
trace
(
"simple_client (%x) exiting
\n
"
,
id
);
client_stop
();
}
/*
* event_client: An event-driven client
*/
static
void
WINAPI
event_client
(
client_params
*
par
)
{
test_params
*
gen
=
par
->
general
;
client_memory
*
mem
;
int
id
=
GetCurrentThreadId
(),
n_expected
=
gen
->
n_chunks
*
gen
->
chunk_size
,
tmp
,
err
,
n
;
HANDLE
event
;
WSANETWORKEVENTS
wsa_events
;
char
*
send_last
,
*
recv_last
,
*
send_p
,
*
recv_p
;
long
mask
=
FD_READ
|
FD_WRITE
|
FD_CLOSE
;
trace
(
"event_client (%x): starting
\n
"
,
id
);
client_start
(
par
);
trace
(
"event_client (%x): server ready
\n
"
,
id
);
mem
=
TlsGetValue
(
tls
);
/* Prepare event notification for connect, makes socket nonblocking */
event
=
WSACreateEvent
();
WSAEventSelect
(
mem
->
s
,
event
,
FD_CONNECT
);
tmp
=
connect
(
mem
->
s
,
(
struct
sockaddr
*
)
&
mem
->
addr
,
sizeof
(
mem
->
addr
)
);
if
(
tmp
!=
0
&&
(
err
=
WSAGetLastError
()
)
!=
WSAEWOULDBLOCK
)
ok
(
0
,
"event_client (%x): connect error: %d"
,
id
,
err
);
tmp
=
WaitForSingleObject
(
event
,
INFINITE
);
ok
(
tmp
==
WAIT_OBJECT_0
,
"event_client (%x): wait for connect event failed: %d"
,
id
,
tmp
);
err
=
WSAEnumNetworkEvents
(
mem
->
s
,
event
,
&
wsa_events
);
wsa_ok
(
err
,
0
==
,
"event_client (%x): WSAEnumNetworkEvents error: %d
\n
"
);
err
=
wsa_events
.
iErrorCode
[
FD_CONNECT_BIT
];
ok
(
err
==
0
,
"event_client (%x): connect error: %d"
,
id
,
err
);
if
(
err
)
goto
out
;
trace
(
"event_client (%x) connected
\n
"
,
id
);
WSAEventSelect
(
mem
->
s
,
event
,
mask
);
recv_p
=
mem
->
recv_buf
;
recv_last
=
mem
->
recv_buf
+
n_expected
;
send_p
=
mem
->
send_buf
;
send_last
=
mem
->
send_buf
+
n_expected
;
while
(
TRUE
)
{
err
=
WaitForSingleObject
(
event
,
INFINITE
);
ok
(
err
==
WAIT_OBJECT_0
,
"event_client (%x): wait failed"
,
id
,
tmp
);
err
=
WSAEnumNetworkEvents
(
mem
->
s
,
event
,
&
wsa_events
);
wsa_ok
(
err
,
0
==
,
"event_client (%x): WSAEnumNetworkEvents error: %d
\n
"
);
if
(
wsa_events
.
lNetworkEvents
&
FD_WRITE
)
{
err
=
wsa_events
.
iErrorCode
[
FD_WRITE_BIT
];
ok
(
err
==
0
,
"event_client (%x): FD_WRITE error code: %d
\n
"
,
id
,
err
);
if
(
err
==
0
)
do
{
n
=
send
(
mem
->
s
,
send_p
,
min
(
send_last
-
send_p
,
par
->
buflen
),
0
);
if
(
n
<
0
)
{
err
=
WSAGetLastError
();
ok
(
err
==
WSAEWOULDBLOCK
,
"event_client (%x): send error: %d
\n
"
,
id
,
err
);
}
else
send_p
+=
n
;
}
while
(
n
>=
0
&&
send_p
<
send_last
);
if
(
send_p
==
send_last
)
{
trace
(
"event_client (%x): all data sent - shutdown
\n
"
,
id
);
shutdown
(
mem
->
s
,
SD_SEND
);
mask
&=
~
FD_WRITE
;
WSAEventSelect
(
mem
->
s
,
event
,
mask
);
}
}
else
if
(
wsa_events
.
lNetworkEvents
&
FD_READ
)
{
err
=
wsa_events
.
iErrorCode
[
FD_READ_BIT
];
ok
(
err
==
0
,
"event_client (%x): FD_READ error code: %d
\n
"
,
id
,
err
);
n
=
recv
(
mem
->
s
,
recv_p
,
min
(
recv_last
-
recv_p
,
par
->
buflen
),
0
);
wsa_ok
(
n
,
0
<=
,
"event_client (%x): recv error: %d
\n
"
);
if
(
err
!=
0
||
n
<
0
)
break
;
else
if
(
n
==
0
)
{
ok
(
0
,
"event_client (%x): empty receive"
,
id
);
break
;
}
recv_p
+=
n
;
if
(
recv_p
==
recv_last
)
{
trace
(
"event_client (%x): all data received
\n
"
,
id
);
mask
&=
~
FD_READ
;
WSAEventSelect
(
mem
->
s
,
event
,
mask
);
}
}
else
if
(
wsa_events
.
lNetworkEvents
&
FD_CLOSE
)
{
trace
(
"event_client (%x): close event
\n
"
,
id
);
err
=
wsa_events
.
iErrorCode
[
FD_CLOSE_BIT
];
ok
(
err
==
0
,
"event_client (%x): FD_CLOSE error code: %d
\n
"
,
id
,
err
);
break
;
}
}
ok
(
send_p
==
send_last
,
"simple_client (%x): sent less data then expected: %d of %d"
,
id
,
send_p
-
mem
->
send_buf
,
n_expected
);
ok
(
recv_p
==
recv_last
,
"simple_client (%x): received less data then expected: %d of %d"
,
id
,
recv_p
-
mem
->
recv_buf
,
n_expected
);
recv_p
=
test_buffer
(
mem
->
recv_buf
,
gen
->
chunk_size
,
gen
->
n_chunks
);
ok
(
recv_p
==
NULL
,
"event_client (%x): test pattern error: %d"
,
id
,
recv_p
-
mem
->
recv_buf
);
out:
WSACloseEvent
(
event
);
trace
(
"event_client (%x) exiting
\n
"
,
id
);
client_stop
();
}
/**************** Main program utility functions ***************/
static
void
Init
(
void
)
{
WORD
ver
=
MAKEWORD
(
2
,
2
);
WSADATA
data
;
ok
(
WSAStartup
(
ver
,
&
data
)
==
0
,
"WSAStartup failed"
);
tls
=
TlsAlloc
();
}
static
void
Exit
(
void
)
{
TlsFree
(
tls
);
ok
(
WSACleanup
()
==
0
,
"WSACleanup failed"
);
}
static
void
StartServer
(
LPTHREAD_START_ROUTINE
routine
,
test_params
*
general
,
server_params
*
par
)
{
par
->
general
=
general
;
thread
[
0
]
=
CreateThread
(
NULL
,
0
,
routine
,
par
,
0
,
&
thread_id
[
0
]
);
ok
(
thread
[
0
]
!=
(
HANDLE
)
NULL
,
"Failed to create server thread"
);
}
static
void
StartClients
(
LPTHREAD_START_ROUTINE
routine
,
test_params
*
general
,
client_params
*
par
)
{
int
i
;
par
->
general
=
general
;
for
(
i
=
1
;
i
<=
min
(
general
->
n_clients
,
MAX_CLIENTS
);
i
++
)
{
client_id
=
i
-
1
;
thread
[
i
]
=
CreateThread
(
NULL
,
0
,
routine
,
par
,
0
,
&
thread_id
[
i
]
);
ok
(
thread
[
i
]
!=
(
HANDLE
)
NULL
,
"Failed to create client thread"
);
/* Make sure the client is up and running */
WaitForSingleObject
(
client_ready
[
client_id
],
INFINITE
);
};
}
static
void
do_test
(
test_setup
*
test
)
{
int
i
,
n
=
min
(
test
->
general
.
n_clients
,
MAX_CLIENTS
);
int
wait
;
server_ready
=
CreateEventA
(
NULL
,
TRUE
,
FALSE
,
NULL
);
for
(
i
=
0
;
i
<=
n
;
i
++
)
client_ready
[
i
]
=
CreateEventA
(
NULL
,
TRUE
,
FALSE
,
NULL
);
StartServer
(
test
->
srv
,
&
test
->
general
,
&
test
->
srv_params
);
StartClients
(
test
->
clt
,
&
test
->
general
,
&
test
->
clt_params
);
WaitForSingleObject
(
server_ready
,
INFINITE
);
wait
=
WaitForMultipleObjects
(
1
+
n
,
thread
,
TRUE
,
1000
*
TEST_TIMEOUT
);
ok
(
wait
==
WAIT_OBJECT_0
,
"some threads have not completed
\n
"
);
if
(
wait
==
WAIT_TIMEOUT
)
{
for
(
i
=
0
;
i
<=
n
;
i
++
)
{
trace
(
"terminating thread %08x
\n
"
,
thread_id
[
i
]);
if
(
WaitForSingleObject
(
thread
[
i
],
0
)
!=
WAIT_OBJECT_0
)
TerminateThread
(
thread
[
i
],
0
);
}
}
CloseHandle
(
server_ready
);
for
(
i
=
0
;
i
<=
n
;
i
++
)
CloseHandle
(
client_ready
[
i
]
);
}
/************* Array containing the tests to run **********/
#define STD_STREAM_SOCKET \
sock_type: SOCK_STREAM, \
sock_prot: 0, \
inet_addr: "127.0.0.1", \
inet_port: 9374
static
test_setup
tests
[
NUM_TESTS
]
=
{
/* Test 0: synchronous client and server */
{
general
:
{
STD_STREAM_SOCKET
,
chunk_size
:
2048
,
n_chunks
:
16
,
n_clients
:
2
},
srv
:
simple_server
,
srv_params
:
{
buflen
:
64
},
clt
:
simple_client
,
clt_params
:
{
buflen
:
128
}
},
/* Test 1: event-driven client, synchronous server */
{
general
:
{
STD_STREAM_SOCKET
,
chunk_size
:
2048
,
n_chunks
:
16
,
n_clients
:
2
},
srv
:
simple_server
,
srv_params
:
{
buflen
:
64
},
clt
:
event_client
,
clt_params
:
{
buflen
:
128
}
}
};
/**************** Main program ***************/
START_TEST
(
sock
)
{
int
i
;
Init
();
for
(
i
=
0
;
i
<
NUM_TESTS
;
i
++
)
{
trace
(
" **** STARTING TEST %d ****
\n
"
,
i
);
do_test
(
&
tests
[
i
]
);
trace
(
" **** TEST %d COMPLETE ****
\n
"
,
i
);
}
Exit
();
}
dlls/winsock/tests/ws2_32_test.spec
0 → 100644
View file @
b28f933b
name ws2_32_test
type win32
mode cuiexe
import ws2_32.dll
import kernel32.dll
import ntdll.dll
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment