[WS2_32_APITEST:WSAASYNC] Fix and improve some tests. ROSTESTS-317 (#1132)
[reactos.git] / modules / rostests / apitests / ws2_32 / WSAAsync.c
1 /*
2 * PROJECT: ReactOS api tests
3 * LICENSE: GPL - See COPYING in the top level directory
4 * PURPOSE: Test for WSAAsync
5 * PROGRAMMERS: Miroslav Mastny
6 */
7
8 #include "ws2_32.h"
9
10 #define SVR_PORT 5000
11 #define WAIT_TIMEOUT_ 10000
12 #define EXIT_FLAGS (FD_ACCEPT|FD_CONNECT)
13 #define MAX_LOOPCOUNT 9u
14
15 START_TEST(WSAAsync)
16 {
17 WSADATA WsaData;
18 SOCKET ServerSocket = INVALID_SOCKET,
19 ClientSocket = INVALID_SOCKET;
20 WSAEVENT ServerEvent = WSA_INVALID_EVENT,
21 ClientEvent = WSA_INVALID_EVENT;
22 struct hostent *ent = NULL;
23 struct sockaddr_in server_addr_in;
24 struct sockaddr_in addr_remote;
25 struct sockaddr_in addr_con_loc;
26 int nConRes, nSockNameRes;
27 int addrsize, len;
28 WSAEVENT fEvents[2];
29 SOCKET fSockets[2];
30 SOCKET sockaccept;
31 WSANETWORKEVENTS WsaNetworkEvents;
32 ULONG ulValue = 1;
33 DWORD dwWait;
34 DWORD dwFlags = 0;
35 struct fd_set select_rfds;
36 struct fd_set select_wfds;
37 struct fd_set select_efds;
38 struct timeval timeval;
39 BOOL ConnectSent = FALSE;
40 unsigned int Addr_con_locLoopCount = 0,
41 ServerSocketLoopCount = 0;
42
43 if (WSAStartup(MAKEWORD(2, 2), &WsaData) != 0)
44 {
45 skip("WSAStartup failed\n");
46 return;
47 }
48
49 ServerSocket = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
50 ClientSocket = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
51 ServerEvent = WSACreateEvent();
52 ClientEvent = WSACreateEvent();
53
54 if (ServerSocket == INVALID_SOCKET)
55 {
56 skip("ERROR: Server socket creation failed\n");
57 return;
58 }
59 if (ClientSocket == INVALID_SOCKET)
60 {
61 skip("ERROR: Client socket creation failed\n");
62 closesocket(ServerSocket);
63 return;
64 }
65 if (ServerEvent == WSA_INVALID_EVENT)
66 {
67 skip("ERROR: Server WSAEvent creation failed\n");
68 closesocket(ClientSocket);
69 closesocket(ServerSocket);
70 return;
71 }
72 if (ClientEvent == WSA_INVALID_EVENT)
73 {
74 skip("ERROR: Client WSAEvent creation failed\n");
75 WSACloseEvent(ServerEvent);
76 closesocket(ClientSocket);
77 closesocket(ServerSocket);
78 return;
79 }
80 ent = gethostbyname("127.0.0.1");
81 if (ent == NULL)
82 {
83 ok(ent != NULL, "ERROR: gethostbyname '127.0.0.1' failed, trying 'localhost'\n");
84 ent = gethostbyname("localhost");
85
86 if (ent == NULL)
87 {
88 skip("ERROR: gethostbyname 'localhost' failed\n");
89 goto done;
90 }
91 }
92
93 server_addr_in.sin_family = AF_INET;
94 server_addr_in.sin_port = htons(SVR_PORT);
95 memcpy(&server_addr_in.sin_addr.S_un.S_addr, ent->h_addr_list[0], 4);
96
97 // Server initialization.
98 trace("Initializing server and client connections ...\n");
99 ok(bind(ServerSocket, (struct sockaddr*)&server_addr_in, sizeof(server_addr_in)) == 0, "ERROR: server bind failed\n");
100 ok(ioctlsocket(ServerSocket, FIONBIO, &ulValue) == 0, "ERROR: server ioctlsocket FIONBIO failed\n");
101 ok(WSAEventSelect(ServerSocket, ServerEvent, FD_ACCEPT | FD_CLOSE) == 0, "ERROR: server accept EventSelect failed\n");
102
103 // Client initialization.
104 ok(WSAEventSelect(ClientSocket, ClientEvent, FD_CONNECT | FD_CLOSE) == 0, "ERROR: client EventSelect failed\n");
105 ok(ioctlsocket(ClientSocket, FIONBIO, &ulValue) == 0, "ERROR: client ioctlsocket FIONBIO failed\n");
106
107 // listen
108 trace("Starting server listening mode ...\n");
109 ok(listen(ServerSocket, SOMAXCONN) == 0, "ERROR: cannot initialize server listen\n");
110
111 trace("Starting client to server connection ...\n");
112 // connect
113 nConRes = connect(ClientSocket, (struct sockaddr*)&server_addr_in, sizeof(server_addr_in));
114 ok(nConRes == SOCKET_ERROR, "ERROR: client connect() result is not SOCKET_ERROR\n");
115 ok(WSAGetLastError() == WSAEWOULDBLOCK, "ERROR: client connect() last error is not WSAEWOULDBLOCK\n");
116
117 fSockets[0] = ServerSocket;
118 fSockets[1] = ClientSocket;
119
120 fEvents[0] = ServerEvent;
121 fEvents[1] = ClientEvent;
122
123 while (dwFlags != EXIT_FLAGS)
124 {
125 dwWait = WaitForMultipleObjects(2, fEvents, FALSE, WAIT_TIMEOUT_);
126
127 if (dwWait != WAIT_OBJECT_0 && // server socket event
128 dwWait != WAIT_OBJECT_0+1) // client socket event
129 {
130 ok(FALSE, "Unknown event received %lu\n", dwWait);
131 skip("ERROR: Connection timeout\n");
132 break;
133 }
134
135 WSAEnumNetworkEvents(fSockets[dwWait-WAIT_OBJECT_0], fEvents[dwWait-WAIT_OBJECT_0], &WsaNetworkEvents);
136
137 if ((WsaNetworkEvents.lNetworkEvents & FD_ACCEPT) != 0)
138 {// connection accepted
139 trace("Event FD_ACCEPT...\n");
140 ok(WsaNetworkEvents.iErrorCode[FD_ACCEPT_BIT] == 0, "Error on accept %d\n", WsaNetworkEvents.iErrorCode[FD_ACCEPT_BIT]);
141 if (WsaNetworkEvents.iErrorCode[FD_ACCEPT_BIT] == 0)
142 {
143 addrsize = sizeof(addr_remote);
144 sockaccept = accept(fSockets[dwWait - WAIT_OBJECT_0], (struct sockaddr*)&addr_remote, &addrsize);
145 ok(sockaccept != INVALID_SOCKET, "ERROR: Connection accept function failed, error %d\n", WSAGetLastError());
146 dwFlags |= FD_ACCEPT;
147 }
148 }
149
150 if ((WsaNetworkEvents.lNetworkEvents & FD_CONNECT) != 0)
151 {// client connected
152 trace("Event FD_CONNECT...\n");
153 ok(WsaNetworkEvents.iErrorCode[FD_CONNECT_BIT] == 0, "Error on connect %d\n", WsaNetworkEvents.iErrorCode[FD_CONNECT_BIT]);
154 if (WsaNetworkEvents.iErrorCode[FD_CONNECT_BIT] == 0)
155 {
156 len = sizeof(addr_con_loc);
157 ok(getsockname(fSockets[dwWait - WAIT_OBJECT_0], (struct sockaddr*)&addr_con_loc, &len) == 0, "\n");
158 dwFlags |= FD_CONNECT;
159 }
160 }
161 }
162 closesocket(sockaccept);
163 closesocket(ServerSocket);
164 closesocket(ClientSocket);
165
166 /* same test but with waiting select and getsockname to return proper values */
167 ServerSocket = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
168 ClientSocket = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
169
170 if (ServerSocket == INVALID_SOCKET)
171 {
172 skip("ERROR: Server socket creation failed\n");
173 return;
174 }
175 if (ClientSocket == INVALID_SOCKET)
176 {
177 skip("ERROR: Client socket creation failed\n");
178 closesocket(ServerSocket);
179 return;
180 }
181 ent = gethostbyname("127.0.0.1");
182 if (ent == NULL)
183 {
184 ok(ent != NULL, "ERROR: gethostbyname '127.0.0.1' failed, trying 'localhost'\n");
185 ent = gethostbyname("localhost");
186
187 if (ent == NULL)
188 {
189 skip("ERROR: gethostbyname 'localhost' failed\n");
190 goto done;
191 }
192 }
193
194 server_addr_in.sin_family = AF_INET;
195 server_addr_in.sin_port = htons(SVR_PORT);
196 memcpy(&server_addr_in.sin_addr.S_un.S_addr, ent->h_addr_list[0], 4);
197
198 // Server initialization.
199 trace("Initializing server and client connections ...\n");
200 ok(bind(ServerSocket, (struct sockaddr*)&server_addr_in, sizeof(server_addr_in)) == 0, "ERROR: server bind failed\n");
201 ok(ioctlsocket(ServerSocket, FIONBIO, &ulValue) == 0, "ERROR: server ioctlsocket FIONBIO failed\n");
202
203 // Client initialization.
204 ok(ioctlsocket(ClientSocket, FIONBIO, &ulValue) == 0, "ERROR: client ioctlsocket FIONBIO failed\n");
205
206 // listen
207 trace("Starting server listening mode ...\n");
208 ok(listen(ServerSocket, SOMAXCONN) == 0, "ERROR: cannot initialize server listen\n");
209
210 memset(&timeval, 0, sizeof(timeval));
211 timeval.tv_usec = WAIT_TIMEOUT_;
212 dwFlags = 0;
213
214 while (dwFlags != EXIT_FLAGS)
215 {
216 len = sizeof(addr_con_loc);
217 nSockNameRes = getsockname(ClientSocket, (struct sockaddr*)&addr_con_loc, &len);
218 if (dwFlags == 0 && !ConnectSent)
219 {
220 ok(nSockNameRes == SOCKET_ERROR, "ERROR: getsockname function failed, expected %d error %d\n", SOCKET_ERROR, nSockNameRes);
221 ok(WSAGetLastError() == WSAEINVAL, "ERROR: getsockname function failed, expected %ld error %d\n", WSAEINVAL, WSAGetLastError());
222 trace("Starting client to server connection ...\n");
223 // connect
224 nConRes = connect(ClientSocket, (struct sockaddr*)&server_addr_in, sizeof(server_addr_in));
225 ok(nConRes == SOCKET_ERROR, "ERROR: client connect() result is not SOCKET_ERROR\n");
226 ok(WSAGetLastError() == WSAEWOULDBLOCK, "ERROR: client connect() last error is not WSAEWOULDBLOCK\n");
227 ConnectSent = TRUE;
228 continue;
229 }
230 else
231 {
232 if (nSockNameRes != 0)
233 ok(FALSE, "ERROR: getsockname function failed, expected 0 error %d\n", nSockNameRes);
234 if (len != sizeof(addr_con_loc))
235 ok(FALSE, "ERROR: getsockname function wrong size, expected %Iu returned %d\n", sizeof(addr_con_loc), len);
236
237 if (addr_con_loc.sin_addr.s_addr == 0ul)
238 {
239 if (++Addr_con_locLoopCount >= MAX_LOOPCOUNT)
240 {
241 ok(FALSE, "Giving up, on getsockname() (%u/%u), as addr_con_loc is not set yet\n",
242 Addr_con_locLoopCount, MAX_LOOPCOUNT);
243 goto done;
244 }
245
246 trace("Looping, for getsockname() (%u/%u), as addr_con_loc is not set yet\n",
247 Addr_con_locLoopCount, MAX_LOOPCOUNT);
248 Sleep(1);
249 continue;
250 }
251
252 if (addr_con_loc.sin_addr.s_addr != server_addr_in.sin_addr.s_addr)
253 ok(FALSE, "ERROR: getsockname function wrong addr, expected %08lx returned %08lx\n", server_addr_in.sin_addr.s_addr, addr_con_loc.sin_addr.s_addr);
254 }
255 if ((dwFlags & FD_ACCEPT) != 0)
256 {// client connected
257 trace("Select CONNECT...\n");
258 dwFlags |= FD_CONNECT;
259 }
260
261 FD_ZERO(&select_rfds);
262 FD_ZERO(&select_wfds);
263 FD_ZERO(&select_efds);
264 FD_SET(ServerSocket, &select_rfds);
265 FD_SET(ClientSocket, &select_rfds);
266 FD_SET(ServerSocket, &select_wfds);
267 FD_SET(ClientSocket, &select_wfds);
268 FD_SET(ServerSocket, &select_efds);
269 FD_SET(ClientSocket, &select_efds);
270 if ((dwFlags & FD_ACCEPT) != 0)
271 {
272 FD_SET(sockaccept, &select_rfds);
273 FD_SET(sockaccept, &select_wfds);
274 FD_SET(sockaccept, &select_efds);
275 }
276 if (select(0, &select_rfds, &select_wfds, &select_efds, &timeval) != 0)
277 {// connection accepted
278 if (dwFlags == (FD_ACCEPT | FD_CONNECT))
279 {
280 trace("Select ACCEPT&CONNECT...\n");
281 ok(FD_ISSET(ClientSocket, &select_wfds), "ClientSocket is not writable\n");
282 ok(FD_ISSET(sockaccept, &select_wfds), "sockaccept is not writable\n");
283 ok(!FD_ISSET(ServerSocket, &select_rfds), "ServerSocket is readable\n");
284 }
285 if (dwFlags == FD_ACCEPT)
286 {
287 trace("Select ACCEPT...\n");
288 ok(!FD_ISSET(ClientSocket, &select_wfds), "ClientSocket is writable\n");
289 ok(FD_ISSET(sockaccept, &select_wfds), "sockaccept is not writable\n");
290 ok(FD_ISSET(ServerSocket, &select_rfds), "ServerSocket is not readable\n");
291 }
292 if (dwFlags == 0)
293 {
294 if (FD_ISSET(ServerSocket, &select_rfds))
295 {
296 trace("Select ACCEPT...\n");
297 addrsize = sizeof(addr_remote);
298 sockaccept = accept(ServerSocket, (struct sockaddr*)&addr_remote, &addrsize);
299 ok(sockaccept != INVALID_SOCKET, "ERROR: Connection accept function failed, error %d\n", WSAGetLastError());
300 dwFlags |= FD_ACCEPT;
301 }
302 else
303 {
304 if (++ServerSocketLoopCount >= MAX_LOOPCOUNT)
305 {
306 ok(FALSE, "Giving up, on select() (%u/%u), as ServerSocket is not readable yet\n",
307 ServerSocketLoopCount, MAX_LOOPCOUNT);
308 goto done;
309 }
310
311 trace("Looping, for select() (%u/%u), as ServerSocket is not readable yet\n",
312 ServerSocketLoopCount, MAX_LOOPCOUNT);
313 Sleep(1);
314 continue;
315 }
316 }
317 }
318 }
319
320 done:
321 WSACloseEvent(ServerEvent);
322 WSACloseEvent(ClientEvent);
323 closesocket(sockaccept);
324 closesocket(ServerSocket);
325 closesocket(ClientSocket);
326
327 WSACleanup();
328 }