makefiles: Don't use standard libs for programs that specify -nodefaultlibs.
[wine/zf.git] / dlls / winhttp / tests / notification.c
blob435e262d18b023285b180c0160edc44c093d5c2a
1 /*
2 * test status notifications
4 * Copyright 2008 Hans Leidekker for CodeWeavers
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.
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.
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., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
21 #include <stdarg.h>
22 #include <stdlib.h>
23 #include <windef.h>
24 #include <winbase.h>
25 #include <winsock2.h>
26 #include <ws2tcpip.h>
27 #include <winhttp.h>
29 #include "wine/test.h"
31 enum api
33 winhttp_connect = 1,
34 winhttp_open_request,
35 winhttp_send_request,
36 winhttp_receive_response,
37 winhttp_query_data,
38 winhttp_read_data,
39 winhttp_write_data,
40 winhttp_close_handle
43 struct notification
45 enum api function; /* api responsible for notification */
46 unsigned int status; /* status received */
47 DWORD flags; /* a combination of NF_* flags */
50 #define NF_ALLOW 0x0001 /* notification may or may not happen */
51 #define NF_WINE_ALLOW 0x0002 /* wine sends notification when it should not */
52 #define NF_SIGNAL 0x0004 /* signal wait handle when notified */
54 struct info
56 enum api function;
57 const struct notification *test;
58 unsigned int count;
59 unsigned int index;
60 HANDLE wait;
61 unsigned int line;
64 struct test_request
66 HINTERNET session;
67 HINTERNET connection;
68 HINTERNET request;
71 static void CALLBACK check_notification( HINTERNET handle, DWORD_PTR context, DWORD status, LPVOID buffer, DWORD buflen )
73 BOOL status_ok, function_ok;
74 struct info *info = (struct info *)context;
76 if (status == WINHTTP_CALLBACK_STATUS_HANDLE_CREATED)
78 DWORD size = sizeof(struct info *);
79 WinHttpQueryOption( handle, WINHTTP_OPTION_CONTEXT_VALUE, &info, &size );
81 while (info->index < info->count && info->test[info->index].status != status && (info->test[info->index].flags & NF_ALLOW))
82 info->index++;
83 while (info->index < info->count && (info->test[info->index].flags & NF_WINE_ALLOW))
85 todo_wine ok(info->test[info->index].status != status, "unexpected %x notification\n", status);
86 if (info->test[info->index].status == status) break;
87 info->index++;
89 ok(info->index < info->count, "%u: unexpected notification 0x%08x\n", info->line, status);
90 if (info->index >= info->count) return;
92 status_ok = (info->test[info->index].status == status);
93 function_ok = (info->test[info->index].function == info->function);
94 ok(status_ok, "%u: expected status 0x%08x got 0x%08x\n", info->line, info->test[info->index].status, status);
95 ok(function_ok, "%u: expected function %u got %u\n", info->line, info->test[info->index].function, info->function);
97 if (status_ok && function_ok && info->test[info->index++].flags & NF_SIGNAL)
99 SetEvent( info->wait );
103 static const struct notification cache_test[] =
105 { winhttp_connect, WINHTTP_CALLBACK_STATUS_HANDLE_CREATED },
106 { winhttp_open_request, WINHTTP_CALLBACK_STATUS_HANDLE_CREATED },
107 { winhttp_send_request, WINHTTP_CALLBACK_STATUS_RESOLVING_NAME },
108 { winhttp_send_request, WINHTTP_CALLBACK_STATUS_NAME_RESOLVED },
109 { winhttp_send_request, WINHTTP_CALLBACK_STATUS_CONNECTING_TO_SERVER },
110 { winhttp_send_request, WINHTTP_CALLBACK_STATUS_CONNECTED_TO_SERVER },
111 { winhttp_send_request, WINHTTP_CALLBACK_STATUS_SENDING_REQUEST },
112 { winhttp_send_request, WINHTTP_CALLBACK_STATUS_REQUEST_SENT },
113 { winhttp_receive_response, WINHTTP_CALLBACK_STATUS_RECEIVING_RESPONSE },
114 { winhttp_receive_response, WINHTTP_CALLBACK_STATUS_RESPONSE_RECEIVED },
115 { winhttp_close_handle, WINHTTP_CALLBACK_STATUS_CLOSING_CONNECTION, NF_WINE_ALLOW },
116 { winhttp_close_handle, WINHTTP_CALLBACK_STATUS_CONNECTION_CLOSED, NF_WINE_ALLOW },
117 { winhttp_close_handle, WINHTTP_CALLBACK_STATUS_HANDLE_CLOSING, NF_SIGNAL },
118 { winhttp_open_request, WINHTTP_CALLBACK_STATUS_HANDLE_CREATED },
119 { winhttp_send_request, WINHTTP_CALLBACK_STATUS_CONNECTING_TO_SERVER, NF_WINE_ALLOW },
120 { winhttp_send_request, WINHTTP_CALLBACK_STATUS_CONNECTED_TO_SERVER, NF_WINE_ALLOW },
121 { winhttp_send_request, WINHTTP_CALLBACK_STATUS_SENDING_REQUEST },
122 { winhttp_send_request, WINHTTP_CALLBACK_STATUS_REQUEST_SENT },
123 { winhttp_receive_response, WINHTTP_CALLBACK_STATUS_RECEIVING_RESPONSE },
124 { winhttp_receive_response, WINHTTP_CALLBACK_STATUS_RESPONSE_RECEIVED },
125 { winhttp_close_handle, WINHTTP_CALLBACK_STATUS_CLOSING_CONNECTION, NF_WINE_ALLOW },
126 { winhttp_close_handle, WINHTTP_CALLBACK_STATUS_CONNECTION_CLOSED, NF_WINE_ALLOW },
127 { winhttp_close_handle, WINHTTP_CALLBACK_STATUS_HANDLE_CLOSING },
128 { winhttp_close_handle, WINHTTP_CALLBACK_STATUS_HANDLE_CLOSING, NF_SIGNAL },
129 { winhttp_close_handle, WINHTTP_CALLBACK_STATUS_HANDLE_CLOSING, NF_SIGNAL },
130 { winhttp_connect, WINHTTP_CALLBACK_STATUS_HANDLE_CREATED },
131 { winhttp_open_request, WINHTTP_CALLBACK_STATUS_HANDLE_CREATED },
132 { winhttp_send_request, WINHTTP_CALLBACK_STATUS_RESOLVING_NAME, NF_WINE_ALLOW },
133 { winhttp_send_request, WINHTTP_CALLBACK_STATUS_NAME_RESOLVED, NF_WINE_ALLOW },
134 { winhttp_send_request, WINHTTP_CALLBACK_STATUS_CONNECTING_TO_SERVER, NF_WINE_ALLOW },
135 { winhttp_send_request, WINHTTP_CALLBACK_STATUS_CONNECTED_TO_SERVER, NF_WINE_ALLOW },
136 { winhttp_send_request, WINHTTP_CALLBACK_STATUS_SENDING_REQUEST },
137 { winhttp_send_request, WINHTTP_CALLBACK_STATUS_REQUEST_SENT },
138 { winhttp_receive_response, WINHTTP_CALLBACK_STATUS_RECEIVING_RESPONSE },
139 { winhttp_receive_response, WINHTTP_CALLBACK_STATUS_RESPONSE_RECEIVED },
140 { winhttp_close_handle, WINHTTP_CALLBACK_STATUS_CLOSING_CONNECTION, NF_WINE_ALLOW },
141 { winhttp_close_handle, WINHTTP_CALLBACK_STATUS_CONNECTION_CLOSED, NF_WINE_ALLOW },
142 { winhttp_close_handle, WINHTTP_CALLBACK_STATUS_HANDLE_CLOSING, NF_SIGNAL },
143 { winhttp_open_request, WINHTTP_CALLBACK_STATUS_HANDLE_CREATED },
144 { winhttp_send_request, WINHTTP_CALLBACK_STATUS_CONNECTING_TO_SERVER, NF_WINE_ALLOW },
145 { winhttp_send_request, WINHTTP_CALLBACK_STATUS_CONNECTED_TO_SERVER, NF_WINE_ALLOW },
146 { winhttp_send_request, WINHTTP_CALLBACK_STATUS_SENDING_REQUEST },
147 { winhttp_send_request, WINHTTP_CALLBACK_STATUS_REQUEST_SENT },
148 { winhttp_receive_response, WINHTTP_CALLBACK_STATUS_RECEIVING_RESPONSE },
149 { winhttp_receive_response, WINHTTP_CALLBACK_STATUS_RESPONSE_RECEIVED },
150 { winhttp_close_handle, WINHTTP_CALLBACK_STATUS_CLOSING_CONNECTION, NF_WINE_ALLOW },
151 { winhttp_close_handle, WINHTTP_CALLBACK_STATUS_CONNECTION_CLOSED, NF_WINE_ALLOW },
152 { winhttp_close_handle, WINHTTP_CALLBACK_STATUS_HANDLE_CLOSING },
153 { winhttp_close_handle, WINHTTP_CALLBACK_STATUS_HANDLE_CLOSING, NF_SIGNAL },
154 { winhttp_close_handle, WINHTTP_CALLBACK_STATUS_HANDLE_CLOSING, NF_SIGNAL }
157 static void setup_test( struct info *info, enum api function, unsigned int line )
159 if (info->wait) ResetEvent( info->wait );
160 info->function = function;
161 info->line = line;
162 while (info->index < info->count && info->test[info->index].function != function
163 && (info->test[info->index].flags & (NF_ALLOW | NF_WINE_ALLOW)))
164 info->index++;
165 ok_(__FILE__,line)(info->test[info->index].function == function,
166 "unexpected function %u, expected %u. probably some notifications were missing\n",
167 info->test[info->index].function, function);
170 static void end_test( struct info *info, unsigned int line )
172 ok_(__FILE__,line)(info->index == info->count, "some notifications were missing: %x\n",
173 info->test[info->index].status);
176 static void test_connection_cache( void )
178 HANDLE ses, con, req, event;
179 DWORD size, status, err;
180 BOOL ret, unload = TRUE;
181 struct info info, *context = &info;
183 info.test = cache_test;
184 info.count = ARRAY_SIZE( cache_test );
185 info.index = 0;
186 info.wait = CreateEventW( NULL, FALSE, FALSE, NULL );
188 ses = WinHttpOpen( L"winetest", 0, NULL, NULL, 0 );
189 ok(ses != NULL, "failed to open session %u\n", GetLastError());
191 event = CreateEventW( NULL, FALSE, FALSE, NULL );
192 ret = WinHttpSetOption( ses, WINHTTP_OPTION_UNLOAD_NOTIFY_EVENT, &event, sizeof(event) );
193 if (!ret)
195 win_skip("Unload event not supported\n");
196 unload = FALSE;
199 WinHttpSetStatusCallback( ses, check_notification, WINHTTP_CALLBACK_FLAG_ALL_NOTIFICATIONS, 0 );
201 ret = WinHttpSetOption( ses, WINHTTP_OPTION_CONTEXT_VALUE, &context, sizeof(struct info *) );
202 ok(ret, "failed to set context value %u\n", GetLastError());
204 setup_test( &info, winhttp_connect, __LINE__ );
205 con = WinHttpConnect( ses, L"test.winehq.org", 0, 0 );
206 ok(con != NULL, "failed to open a connection %u\n", GetLastError());
208 setup_test( &info, winhttp_open_request, __LINE__ );
209 req = WinHttpOpenRequest( con, NULL, L"/tests/hello.html", NULL, NULL, NULL, 0 );
210 ok(req != NULL, "failed to open a request %u\n", GetLastError());
212 setup_test( &info, winhttp_send_request, __LINE__ );
213 ret = WinHttpSendRequest( req, NULL, 0, NULL, 0, 0, 0 );
214 err = GetLastError();
215 if (!ret && (err == ERROR_WINHTTP_CANNOT_CONNECT || err == ERROR_WINHTTP_TIMEOUT))
217 skip("connection failed, skipping\n");
218 goto done;
220 ok(ret, "failed to send request %u\n", GetLastError());
222 setup_test( &info, winhttp_receive_response, __LINE__ );
223 ret = WinHttpReceiveResponse( req, NULL );
224 ok(ret, "failed to receive response %u\n", GetLastError());
226 size = sizeof(status);
227 ret = WinHttpQueryHeaders( req, WINHTTP_QUERY_STATUS_CODE | WINHTTP_QUERY_FLAG_NUMBER, NULL, &status, &size, NULL );
228 ok(ret, "failed unexpectedly %u\n", GetLastError());
229 ok(status == 200, "request failed unexpectedly %u\n", status);
231 ResetEvent( info.wait );
232 setup_test( &info, winhttp_close_handle, __LINE__ );
233 WinHttpCloseHandle( req );
234 WaitForSingleObject( info.wait, INFINITE );
236 setup_test( &info, winhttp_open_request, __LINE__ );
237 req = WinHttpOpenRequest( con, NULL, L"/tests/hello.html", NULL, NULL, NULL, 0 );
238 ok(req != NULL, "failed to open a request %u\n", GetLastError());
240 ret = WinHttpSetOption( req, WINHTTP_OPTION_CONTEXT_VALUE, &context, sizeof(struct info *) );
241 ok(ret, "failed to set context value %u\n", GetLastError());
243 setup_test( &info, winhttp_send_request, __LINE__ );
244 ret = WinHttpSendRequest( req, NULL, 0, NULL, 0, 0, 0 );
245 err = GetLastError();
246 if (!ret && (err == ERROR_WINHTTP_CANNOT_CONNECT || err == ERROR_WINHTTP_TIMEOUT))
248 skip("connection failed, skipping\n");
249 goto done;
251 ok(ret, "failed to send request %u\n", GetLastError());
253 setup_test( &info, winhttp_receive_response, __LINE__ );
254 ret = WinHttpReceiveResponse( req, NULL );
255 ok(ret, "failed to receive response %u\n", GetLastError());
257 size = sizeof(status);
258 ret = WinHttpQueryHeaders( req, WINHTTP_QUERY_STATUS_CODE | WINHTTP_QUERY_FLAG_NUMBER, NULL, &status, &size, NULL );
259 ok(ret, "failed unexpectedly %u\n", GetLastError());
260 ok(status == 200, "request failed unexpectedly %u\n", status);
262 ResetEvent( info.wait );
263 setup_test( &info, winhttp_close_handle, __LINE__ );
264 WinHttpCloseHandle( req );
265 WinHttpCloseHandle( req );
266 WinHttpCloseHandle( con );
267 WaitForSingleObject( info.wait, INFINITE );
269 if (unload)
271 status = WaitForSingleObject( event, 0 );
272 ok(status == WAIT_TIMEOUT, "got %08x\n", status);
275 setup_test( &info, winhttp_close_handle, __LINE__ );
276 WinHttpCloseHandle( ses );
277 WaitForSingleObject( info.wait, INFINITE );
279 if (unload)
281 status = WaitForSingleObject( event, 100 );
282 ok(status == WAIT_OBJECT_0, "got %08x\n", status);
286 ses = WinHttpOpen( L"winetest", 0, NULL, NULL, 0 );
287 ok(ses != NULL, "failed to open session %u\n", GetLastError());
289 if (unload)
291 ret = WinHttpSetOption( ses, WINHTTP_OPTION_UNLOAD_NOTIFY_EVENT, &event, sizeof(event) );
292 ok(ret, "failed to set unload option\n");
295 WinHttpSetStatusCallback( ses, check_notification, WINHTTP_CALLBACK_FLAG_ALL_NOTIFICATIONS, 0 );
297 ret = WinHttpSetOption( ses, WINHTTP_OPTION_CONTEXT_VALUE, &context, sizeof(struct info *) );
298 ok(ret, "failed to set context value %u\n", GetLastError());
300 setup_test( &info, winhttp_connect, __LINE__ );
301 con = WinHttpConnect( ses, L"test.winehq.org", 0, 0 );
302 ok(con != NULL, "failed to open a connection %u\n", GetLastError());
304 setup_test( &info, winhttp_open_request, __LINE__ );
305 req = WinHttpOpenRequest( con, NULL, L"/tests/hello.html", NULL, NULL, NULL, 0 );
306 ok(req != NULL, "failed to open a request %u\n", GetLastError());
308 ret = WinHttpSetOption( req, WINHTTP_OPTION_CONTEXT_VALUE, &context, sizeof(struct info *) );
309 ok(ret, "failed to set context value %u\n", GetLastError());
311 setup_test( &info, winhttp_send_request, __LINE__ );
312 ret = WinHttpSendRequest( req, NULL, 0, NULL, 0, 0, 0 );
313 err = GetLastError();
314 if (!ret && (err == ERROR_WINHTTP_CANNOT_CONNECT || err == ERROR_WINHTTP_TIMEOUT))
316 skip("connection failed, skipping\n");
317 goto done;
319 ok(ret, "failed to send request %u\n", GetLastError());
321 setup_test( &info, winhttp_receive_response, __LINE__ );
322 ret = WinHttpReceiveResponse( req, NULL );
323 ok(ret, "failed to receive response %u\n", GetLastError());
325 size = sizeof(status);
326 ret = WinHttpQueryHeaders( req, WINHTTP_QUERY_STATUS_CODE | WINHTTP_QUERY_FLAG_NUMBER, NULL, &status, &size, NULL );
327 ok(ret, "failed unexpectedly %u\n", GetLastError());
328 ok(status == 200, "request failed unexpectedly %u\n", status);
330 ResetEvent( info.wait );
331 setup_test( &info, winhttp_close_handle, __LINE__ );
332 WinHttpCloseHandle( req );
333 WaitForSingleObject( info.wait, INFINITE );
335 setup_test( &info, winhttp_open_request, __LINE__ );
336 req = WinHttpOpenRequest( con, NULL, L"/tests/hello.html", NULL, NULL, NULL, 0 );
337 ok(req != NULL, "failed to open a request %u\n", GetLastError());
339 ret = WinHttpSetOption( req, WINHTTP_OPTION_CONTEXT_VALUE, &context, sizeof(struct info *) );
340 ok(ret, "failed to set context value %u\n", GetLastError());
342 setup_test( &info, winhttp_send_request, __LINE__ );
343 ret = WinHttpSendRequest( req, NULL, 0, NULL, 0, 0, 0 );
344 err = GetLastError();
345 if (!ret && (err == ERROR_WINHTTP_CANNOT_CONNECT || err == ERROR_WINHTTP_TIMEOUT))
347 skip("connection failed, skipping\n");
348 goto done;
350 ok(ret, "failed to send request %u\n", GetLastError());
352 setup_test( &info, winhttp_receive_response, __LINE__ );
353 ret = WinHttpReceiveResponse( req, NULL );
354 ok(ret, "failed to receive response %u\n", GetLastError());
356 size = sizeof(status);
357 ret = WinHttpQueryHeaders( req, WINHTTP_QUERY_STATUS_CODE | WINHTTP_QUERY_FLAG_NUMBER, NULL, &status, &size, NULL );
358 ok(ret, "failed unexpectedly %u\n", GetLastError());
359 ok(status == 200, "request failed unexpectedly %u\n", status);
361 setup_test( &info, winhttp_close_handle, __LINE__ );
362 done:
363 WinHttpCloseHandle( req );
364 WinHttpCloseHandle( con );
365 WaitForSingleObject( info.wait, INFINITE );
367 if (unload)
369 status = WaitForSingleObject( event, 0 );
370 ok(status == WAIT_TIMEOUT, "got %08x\n", status);
373 setup_test( &info, winhttp_close_handle, __LINE__ );
374 WinHttpCloseHandle( ses );
375 WaitForSingleObject( info.wait, INFINITE );
376 CloseHandle( info.wait );
377 end_test( &info, __LINE__ );
379 if (unload)
381 status = WaitForSingleObject( event, 100 );
382 ok(status == WAIT_OBJECT_0, "got %08x\n", status);
385 CloseHandle( event );
388 static const struct notification redirect_test[] =
390 { winhttp_connect, WINHTTP_CALLBACK_STATUS_HANDLE_CREATED },
391 { winhttp_open_request, WINHTTP_CALLBACK_STATUS_HANDLE_CREATED },
392 { winhttp_send_request, WINHTTP_CALLBACK_STATUS_RESOLVING_NAME, NF_WINE_ALLOW },
393 { winhttp_send_request, WINHTTP_CALLBACK_STATUS_NAME_RESOLVED, NF_WINE_ALLOW },
394 { winhttp_send_request, WINHTTP_CALLBACK_STATUS_CONNECTING_TO_SERVER, NF_WINE_ALLOW },
395 { winhttp_send_request, WINHTTP_CALLBACK_STATUS_CONNECTED_TO_SERVER, NF_WINE_ALLOW },
396 { winhttp_send_request, WINHTTP_CALLBACK_STATUS_SENDING_REQUEST },
397 { winhttp_send_request, WINHTTP_CALLBACK_STATUS_REQUEST_SENT },
398 { winhttp_receive_response, WINHTTP_CALLBACK_STATUS_RECEIVING_RESPONSE },
399 { winhttp_receive_response, WINHTTP_CALLBACK_STATUS_RESPONSE_RECEIVED },
400 { winhttp_receive_response, WINHTTP_CALLBACK_STATUS_REDIRECT },
401 { winhttp_receive_response, WINHTTP_CALLBACK_STATUS_RESOLVING_NAME, NF_ALLOW },
402 { winhttp_receive_response, WINHTTP_CALLBACK_STATUS_NAME_RESOLVED, NF_ALLOW },
403 { winhttp_receive_response, WINHTTP_CALLBACK_STATUS_CONNECTING_TO_SERVER, NF_ALLOW },
404 { winhttp_receive_response, WINHTTP_CALLBACK_STATUS_CONNECTED_TO_SERVER, NF_ALLOW },
405 { winhttp_receive_response, WINHTTP_CALLBACK_STATUS_SENDING_REQUEST },
406 { winhttp_receive_response, WINHTTP_CALLBACK_STATUS_REQUEST_SENT },
407 { winhttp_receive_response, WINHTTP_CALLBACK_STATUS_RECEIVING_RESPONSE },
408 { winhttp_receive_response, WINHTTP_CALLBACK_STATUS_RESPONSE_RECEIVED },
409 { winhttp_close_handle, WINHTTP_CALLBACK_STATUS_CLOSING_CONNECTION, NF_WINE_ALLOW },
410 { winhttp_close_handle, WINHTTP_CALLBACK_STATUS_CONNECTION_CLOSED, NF_WINE_ALLOW },
411 { winhttp_close_handle, WINHTTP_CALLBACK_STATUS_HANDLE_CLOSING },
412 { winhttp_close_handle, WINHTTP_CALLBACK_STATUS_HANDLE_CLOSING },
413 { winhttp_close_handle, WINHTTP_CALLBACK_STATUS_HANDLE_CLOSING, NF_SIGNAL }
416 static void test_redirect( void )
418 HANDLE ses, con, req;
419 DWORD size, status, err;
420 BOOL ret;
421 struct info info, *context = &info;
423 info.test = redirect_test;
424 info.count = ARRAY_SIZE( redirect_test );
425 info.index = 0;
426 info.wait = CreateEventW( NULL, FALSE, FALSE, NULL );
428 ses = WinHttpOpen( L"winetest", 0, NULL, NULL, 0 );
429 ok(ses != NULL, "failed to open session %u\n", GetLastError());
431 WinHttpSetStatusCallback( ses, check_notification, WINHTTP_CALLBACK_FLAG_ALL_NOTIFICATIONS, 0 );
433 ret = WinHttpSetOption( ses, WINHTTP_OPTION_CONTEXT_VALUE, &context, sizeof(struct info *) );
434 ok(ret, "failed to set context value %u\n", GetLastError());
436 setup_test( &info, winhttp_connect, __LINE__ );
437 con = WinHttpConnect( ses, L"test.winehq.org", 0, 0 );
438 ok(con != NULL, "failed to open a connection %u\n", GetLastError());
440 setup_test( &info, winhttp_open_request, __LINE__ );
441 req = WinHttpOpenRequest( con, NULL, L"/tests/redirect", NULL, NULL, NULL, 0 );
442 ok(req != NULL, "failed to open a request %u\n", GetLastError());
444 setup_test( &info, winhttp_send_request, __LINE__ );
445 ret = WinHttpSendRequest( req, NULL, 0, NULL, 0, 0, 0 );
446 err = GetLastError();
447 if (!ret && (err == ERROR_WINHTTP_CANNOT_CONNECT || err == ERROR_WINHTTP_TIMEOUT))
449 skip("connection failed, skipping\n");
450 goto done;
452 ok(ret, "failed to send request %u\n", GetLastError());
454 setup_test( &info, winhttp_receive_response, __LINE__ );
455 ret = WinHttpReceiveResponse( req, NULL );
456 ok(ret, "failed to receive response %u\n", GetLastError());
458 size = sizeof(status);
459 ret = WinHttpQueryHeaders( req, WINHTTP_QUERY_STATUS_CODE | WINHTTP_QUERY_FLAG_NUMBER, NULL, &status, &size, NULL );
460 ok(ret, "failed unexpectedly %u\n", GetLastError());
461 ok(status == 200, "request failed unexpectedly %u\n", status);
463 setup_test( &info, winhttp_close_handle, __LINE__ );
464 done:
465 WinHttpCloseHandle( req );
466 WinHttpCloseHandle( con );
467 WinHttpCloseHandle( ses );
468 WaitForSingleObject( info.wait, INFINITE );
469 CloseHandle( info.wait );
470 end_test( &info, __LINE__ );
473 static const struct notification async_test[] =
475 { winhttp_connect, WINHTTP_CALLBACK_STATUS_HANDLE_CREATED },
476 { winhttp_open_request, WINHTTP_CALLBACK_STATUS_HANDLE_CREATED },
477 { winhttp_send_request, WINHTTP_CALLBACK_STATUS_RESOLVING_NAME, NF_WINE_ALLOW },
478 { winhttp_send_request, WINHTTP_CALLBACK_STATUS_NAME_RESOLVED, NF_WINE_ALLOW },
479 { winhttp_send_request, WINHTTP_CALLBACK_STATUS_CONNECTING_TO_SERVER, NF_WINE_ALLOW },
480 { winhttp_send_request, WINHTTP_CALLBACK_STATUS_CONNECTED_TO_SERVER, NF_WINE_ALLOW },
481 { winhttp_send_request, WINHTTP_CALLBACK_STATUS_SENDING_REQUEST },
482 { winhttp_send_request, WINHTTP_CALLBACK_STATUS_REQUEST_SENT },
483 { winhttp_send_request, WINHTTP_CALLBACK_STATUS_SENDREQUEST_COMPLETE, NF_SIGNAL },
484 { winhttp_receive_response, WINHTTP_CALLBACK_STATUS_RECEIVING_RESPONSE },
485 { winhttp_receive_response, WINHTTP_CALLBACK_STATUS_RESPONSE_RECEIVED },
486 { winhttp_receive_response, WINHTTP_CALLBACK_STATUS_HEADERS_AVAILABLE, NF_SIGNAL },
487 { winhttp_query_data, WINHTTP_CALLBACK_STATUS_DATA_AVAILABLE, NF_SIGNAL },
488 { winhttp_read_data, WINHTTP_CALLBACK_STATUS_RECEIVING_RESPONSE, NF_ALLOW },
489 { winhttp_read_data, WINHTTP_CALLBACK_STATUS_RESPONSE_RECEIVED, NF_ALLOW },
490 { winhttp_read_data, WINHTTP_CALLBACK_STATUS_READ_COMPLETE, NF_SIGNAL },
491 { winhttp_close_handle, WINHTTP_CALLBACK_STATUS_HANDLE_CLOSING },
492 { winhttp_close_handle, WINHTTP_CALLBACK_STATUS_HANDLE_CLOSING },
493 { winhttp_close_handle, WINHTTP_CALLBACK_STATUS_HANDLE_CLOSING, NF_SIGNAL }
496 static void test_async( void )
498 HANDLE ses, con, req, event;
499 DWORD size, status, err;
500 BOOL ret, unload = TRUE;
501 struct info info, *context = &info;
502 char buffer[1024];
504 info.test = async_test;
505 info.count = ARRAY_SIZE( async_test );
506 info.index = 0;
507 info.wait = CreateEventW( NULL, FALSE, FALSE, NULL );
509 ses = WinHttpOpen( L"winetest", 0, NULL, NULL, WINHTTP_FLAG_ASYNC );
510 ok(ses != NULL, "failed to open session %u\n", GetLastError());
512 event = CreateEventW( NULL, FALSE, FALSE, NULL );
513 ret = WinHttpSetOption( ses, WINHTTP_OPTION_UNLOAD_NOTIFY_EVENT, &event, sizeof(event) );
514 if (!ret)
516 win_skip("Unload event not supported\n");
517 unload = FALSE;
520 SetLastError( 0xdeadbeef );
521 WinHttpSetStatusCallback( ses, check_notification, WINHTTP_CALLBACK_FLAG_ALL_NOTIFICATIONS, 0 );
522 err = GetLastError();
523 ok(err == ERROR_SUCCESS || broken(err == 0xdeadbeef) /* < win7 */, "got %u\n", err);
525 SetLastError( 0xdeadbeef );
526 ret = WinHttpSetOption( ses, WINHTTP_OPTION_CONTEXT_VALUE, &context, sizeof(struct info *) );
527 err = GetLastError();
528 ok(ret, "failed to set context value %u\n", err);
529 ok(err == ERROR_SUCCESS || broken(err == 0xdeadbeef) /* < win7 */, "got %u\n", err);
531 setup_test( &info, winhttp_connect, __LINE__ );
532 SetLastError( 0xdeadbeef );
533 con = WinHttpConnect( ses, L"test.winehq.org", 0, 0 );
534 err = GetLastError();
535 ok(con != NULL, "failed to open a connection %u\n", err);
536 ok(err == ERROR_SUCCESS || broken(err == WSAEINVAL) /* < win7 */, "got %u\n", err);
538 setup_test( &info, winhttp_open_request, __LINE__ );
539 SetLastError( 0xdeadbeef );
540 req = WinHttpOpenRequest( con, NULL, L"/tests/hello.html", NULL, NULL, NULL, 0 );
541 err = GetLastError();
542 ok(req != NULL, "failed to open a request %u\n", err);
543 ok(err == ERROR_SUCCESS, "got %u\n", err);
545 setup_test( &info, winhttp_send_request, __LINE__ );
546 SetLastError( 0xdeadbeef );
547 ret = WinHttpSendRequest( req, NULL, 0, NULL, 0, 0, 0 );
548 err = GetLastError();
549 if (!ret && (err == ERROR_WINHTTP_CANNOT_CONNECT || err == ERROR_WINHTTP_TIMEOUT))
551 skip("connection failed, skipping\n");
552 WinHttpCloseHandle( req );
553 WinHttpCloseHandle( con );
554 WinHttpCloseHandle( ses );
555 CloseHandle( info.wait );
556 return;
558 ok(ret, "failed to send request %u\n", err);
559 ok(err == ERROR_SUCCESS, "got %u\n", err);
561 WaitForSingleObject( info.wait, INFINITE );
563 setup_test( &info, winhttp_receive_response, __LINE__ );
564 SetLastError( 0xdeadbeef );
565 ret = WinHttpReceiveResponse( req, NULL );
566 err = GetLastError();
567 ok(ret, "failed to receive response %u\n", err);
568 ok(err == ERROR_SUCCESS, "got %u\n", err);
570 WaitForSingleObject( info.wait, INFINITE );
572 size = sizeof(status);
573 SetLastError( 0xdeadbeef );
574 ret = WinHttpQueryHeaders( req, WINHTTP_QUERY_STATUS_CODE | WINHTTP_QUERY_FLAG_NUMBER, NULL, &status, &size, NULL );
575 err = GetLastError();
576 ok(ret, "failed unexpectedly %u\n", err);
577 ok(status == 200, "request failed unexpectedly %u\n", status);
578 ok(err == ERROR_SUCCESS || broken(err == 0xdeadbeef) /* < win7 */, "got %u\n", err);
580 setup_test( &info, winhttp_query_data, __LINE__ );
581 SetLastError( 0xdeadbeef );
582 ret = WinHttpQueryDataAvailable( req, NULL );
583 err = GetLastError();
584 ok(ret, "failed to query data available %u\n", err);
585 ok(err == ERROR_SUCCESS || err == ERROR_IO_PENDING || broken(err == 0xdeadbeef) /* < win7 */, "got %u\n", err);
587 WaitForSingleObject( info.wait, INFINITE );
589 setup_test( &info, winhttp_read_data, __LINE__ );
590 ret = WinHttpReadData( req, buffer, sizeof(buffer), NULL );
591 ok(ret, "failed to read data %u\n", err);
593 WaitForSingleObject( info.wait, INFINITE );
595 setup_test( &info, winhttp_close_handle, __LINE__ );
596 WinHttpCloseHandle( req );
597 WinHttpCloseHandle( con );
599 if (unload)
601 status = WaitForSingleObject( event, 0 );
602 ok(status == WAIT_TIMEOUT, "got %08x\n", status);
604 WinHttpCloseHandle( ses );
605 WaitForSingleObject( info.wait, INFINITE );
606 end_test( &info, __LINE__ );
608 if (unload)
610 status = WaitForSingleObject( event, 2000 );
611 ok(status == WAIT_OBJECT_0, "got %08x\n", status);
613 CloseHandle( event );
614 CloseHandle( info.wait );
615 end_test( &info, __LINE__ );
618 static const char okmsg[] =
619 "HTTP/1.1 200 OK\r\n"
620 "Server: winetest\r\n"
621 "\r\n";
623 static const char page1[] =
624 "<HTML>\r\n"
625 "<HEAD><TITLE>winhttp test page</TITLE></HEAD>\r\n"
626 "<BODY>The quick brown fox jumped over the lazy dog<P></BODY>\r\n"
627 "</HTML>\r\n\r\n";
629 struct server_info
631 HANDLE event;
632 int port;
635 static int server_socket;
636 static HANDLE server_socket_available, server_socket_done;
638 static DWORD CALLBACK server_thread(LPVOID param)
640 struct server_info *si = param;
641 int r, c = -1, i, on;
642 SOCKET s;
643 struct sockaddr_in sa;
644 char buffer[0x100];
645 WSADATA wsaData;
646 int last_request = 0;
648 WSAStartup(MAKEWORD(1,1), &wsaData);
650 s = socket(AF_INET, SOCK_STREAM, 0);
651 if (s == INVALID_SOCKET)
652 return 1;
654 on = 1;
655 setsockopt(s, SOL_SOCKET, SO_REUSEADDR, (char*)&on, sizeof on);
657 memset(&sa, 0, sizeof sa);
658 sa.sin_family = AF_INET;
659 sa.sin_port = htons(si->port);
660 sa.sin_addr.S_un.S_addr = inet_addr("127.0.0.1");
662 r = bind(s, (struct sockaddr *)&sa, sizeof(sa));
663 if (r < 0)
664 return 1;
666 listen(s, 0);
667 SetEvent(si->event);
670 if (c == -1) c = accept(s, NULL, NULL);
672 memset(buffer, 0, sizeof buffer);
673 for(i = 0; i < sizeof buffer - 1; i++)
675 r = recv(c, &buffer[i], 1, 0);
676 if (r != 1)
677 break;
678 if (i < 4) continue;
679 if (buffer[i - 2] == '\n' && buffer[i] == '\n' &&
680 buffer[i - 3] == '\r' && buffer[i - 1] == '\r')
681 break;
683 if (strstr(buffer, "GET /quit"))
685 send(c, okmsg, sizeof okmsg - 1, 0);
686 send(c, page1, sizeof page1 - 1, 0);
687 last_request = 1;
689 else if(strstr(buffer, "GET /socket"))
691 server_socket = c;
692 SetEvent(server_socket_available);
693 WaitForSingleObject(server_socket_done, INFINITE);
694 ResetEvent(server_socket_available);
696 shutdown(c, 2);
697 closesocket(c);
698 c = -1;
699 } while (!last_request);
701 closesocket(s);
702 return 0;
705 static void test_basic_request(int port, const WCHAR *verb, const WCHAR *path)
707 HINTERNET ses, con, req;
708 char buffer[0x100];
709 DWORD count, status, size;
710 BOOL ret;
712 ses = WinHttpOpen(NULL, WINHTTP_ACCESS_TYPE_NO_PROXY, NULL, NULL, 0);
713 ok(ses != NULL, "failed to open session %u\n", GetLastError());
715 con = WinHttpConnect(ses, L"localhost", port, 0);
716 ok(con != NULL, "failed to open a connection %u\n", GetLastError());
718 req = WinHttpOpenRequest(con, verb, path, NULL, NULL, NULL, 0);
719 ok(req != NULL, "failed to open a request %u\n", GetLastError());
721 ret = WinHttpSendRequest(req, NULL, 0, NULL, 0, 0, 0);
722 ok(ret, "failed to send request %u\n", GetLastError());
724 ret = WinHttpReceiveResponse(req, NULL);
725 ok(ret, "failed to receive response %u\n", GetLastError());
727 status = 0xdeadbeef;
728 size = sizeof(status);
729 ret = WinHttpQueryHeaders(req, WINHTTP_QUERY_STATUS_CODE|WINHTTP_QUERY_FLAG_NUMBER, NULL, &status, &size, NULL);
730 ok(ret, "failed to query status code %u\n", GetLastError());
731 ok(status == HTTP_STATUS_OK, "request failed unexpectedly %u\n", status);
733 count = 0;
734 memset(buffer, 0, sizeof(buffer));
735 ret = WinHttpReadData(req, buffer, sizeof buffer, &count);
736 ok(ret, "failed to read data %u\n", GetLastError());
737 ok(count == sizeof page1 - 1, "count was wrong\n");
738 ok(!memcmp(buffer, page1, sizeof page1), "http data wrong\n");
740 WinHttpCloseHandle(req);
741 WinHttpCloseHandle(con);
742 WinHttpCloseHandle(ses);
745 static const struct notification open_socket_request_test[] =
747 { winhttp_connect, WINHTTP_CALLBACK_STATUS_HANDLE_CREATED },
748 { winhttp_open_request, WINHTTP_CALLBACK_STATUS_HANDLE_CREATED },
749 { winhttp_send_request, WINHTTP_CALLBACK_STATUS_RESOLVING_NAME },
750 { winhttp_send_request, WINHTTP_CALLBACK_STATUS_NAME_RESOLVED },
751 { winhttp_send_request, WINHTTP_CALLBACK_STATUS_CONNECTING_TO_SERVER },
752 { winhttp_send_request, WINHTTP_CALLBACK_STATUS_CONNECTING_TO_SERVER, NF_ALLOW }, /* some versions call it twice. why? */
753 { winhttp_send_request, WINHTTP_CALLBACK_STATUS_CONNECTED_TO_SERVER },
754 { winhttp_send_request, WINHTTP_CALLBACK_STATUS_SENDING_REQUEST },
755 { winhttp_send_request, WINHTTP_CALLBACK_STATUS_REQUEST_SENT },
756 { winhttp_send_request, WINHTTP_CALLBACK_STATUS_SENDREQUEST_COMPLETE, NF_SIGNAL }
759 static const struct notification reuse_socket_request_test[] =
761 { winhttp_connect, WINHTTP_CALLBACK_STATUS_HANDLE_CREATED },
762 { winhttp_open_request, WINHTTP_CALLBACK_STATUS_HANDLE_CREATED },
763 { winhttp_send_request, WINHTTP_CALLBACK_STATUS_SENDING_REQUEST },
764 { winhttp_send_request, WINHTTP_CALLBACK_STATUS_REQUEST_SENT },
765 { winhttp_send_request, WINHTTP_CALLBACK_STATUS_SENDREQUEST_COMPLETE, NF_SIGNAL },
768 static void open_async_request(int port, struct test_request *req, struct info *info, const WCHAR *path, BOOL reuse_connection)
770 BOOL ret;
772 info->index = 0;
773 if (reuse_connection)
775 info->test = reuse_socket_request_test;
776 info->count = ARRAY_SIZE( reuse_socket_request_test );
778 else
780 info->test = open_socket_request_test;
781 info->count = ARRAY_SIZE( open_socket_request_test );
784 req->session = WinHttpOpen( L"winetest", 0, NULL, NULL, WINHTTP_FLAG_ASYNC );
785 ok(req->session != NULL, "failed to open session %u\n", GetLastError());
787 WinHttpSetOption( req->session, WINHTTP_OPTION_CONTEXT_VALUE, &info, sizeof(struct info *) );
788 WinHttpSetStatusCallback( req->session, check_notification, WINHTTP_CALLBACK_FLAG_ALL_NOTIFICATIONS, 0 );
790 setup_test( info, winhttp_connect, __LINE__ );
791 req->connection = WinHttpConnect( req->session, L"localhost", port, 0 );
792 ok(req->connection != NULL, "failed to open a connection %u\n", GetLastError());
794 setup_test( info, winhttp_open_request, __LINE__ );
795 req->request = WinHttpOpenRequest( req->connection, NULL, path, NULL, NULL, NULL, 0 );
796 ok(req->request != NULL, "failed to open a request %u\n", GetLastError());
798 setup_test( info, winhttp_send_request, __LINE__ );
799 ret = WinHttpSendRequest( req->request, NULL, 0, NULL, 0, 0, 0 );
800 ok(ret, "failed to send request %u\n", GetLastError());
803 static void open_socket_request(int port, struct test_request *req, struct info *info)
805 ResetEvent( server_socket_done );
806 open_async_request( port, req, info, L"/socket", FALSE );
807 WaitForSingleObject( server_socket_available, INFINITE );
810 static const struct notification server_reply_test[] =
812 { winhttp_send_request, WINHTTP_CALLBACK_STATUS_RECEIVING_RESPONSE, NF_ALLOW },
813 { winhttp_send_request, WINHTTP_CALLBACK_STATUS_RESPONSE_RECEIVED, NF_ALLOW },
814 { winhttp_send_request, WINHTTP_CALLBACK_STATUS_HEADERS_AVAILABLE, NF_SIGNAL }
817 static void server_send_reply(struct test_request *req, struct info *info, const char *msg)
819 BOOL ret;
821 send( server_socket, msg, strlen( msg ), 0 );
822 WaitForSingleObject( info->wait, INFINITE );
824 info->test = server_reply_test;
825 info->count = ARRAY_SIZE( server_reply_test );
826 info->index = 0;
827 setup_test( info, winhttp_send_request, __LINE__ );
828 ret = WinHttpReceiveResponse( req->request, NULL );
829 ok(ret, "failed to receive response %u\n", GetLastError());
831 WaitForSingleObject( info->wait, INFINITE );
832 end_test( info, __LINE__ );
835 #define server_read_data(a) _server_read_data(a,__LINE__)
836 static void _server_read_data(const char *expect_prefix, unsigned int line)
838 char buf[1024];
839 DWORD size, len;
841 size = recv( server_socket, buf, sizeof(buf), 0 );
842 len = strlen( expect_prefix );
843 ok_(__FILE__,line)(size > len, "data too short\n");
844 if (size >= len)
846 buf[len] = 0;
847 ok_(__FILE__,line)(!strcmp( buf, expect_prefix ), "unexpected data \"%s\"\n", buf);
851 static const struct notification close_request_test[] =
853 { winhttp_close_handle, WINHTTP_CALLBACK_STATUS_HANDLE_CLOSING },
854 { winhttp_close_handle, WINHTTP_CALLBACK_STATUS_HANDLE_CLOSING },
855 { winhttp_close_handle, WINHTTP_CALLBACK_STATUS_HANDLE_CLOSING, NF_SIGNAL }
858 static const struct notification close_allow_connection_close_request_test[] =
860 { winhttp_close_handle, WINHTTP_CALLBACK_STATUS_CLOSING_CONNECTION, NF_ALLOW },
861 { winhttp_close_handle, WINHTTP_CALLBACK_STATUS_CONNECTION_CLOSED, NF_ALLOW },
862 { winhttp_close_handle, WINHTTP_CALLBACK_STATUS_HANDLE_CLOSING },
863 { winhttp_close_handle, WINHTTP_CALLBACK_STATUS_HANDLE_CLOSING },
864 { winhttp_close_handle, WINHTTP_CALLBACK_STATUS_HANDLE_CLOSING, NF_SIGNAL }
867 static void close_request(struct test_request *req, struct info *info, BOOL allow_closing_connection)
869 BOOL ret;
871 if (allow_closing_connection)
873 info->test = close_allow_connection_close_request_test;
874 info->count = ARRAY_SIZE( close_allow_connection_close_request_test );
876 else
878 info->test = close_request_test;
879 info->count = ARRAY_SIZE( close_request_test );
881 info->index = 0;
882 setup_test( info, winhttp_close_handle, __LINE__ );
884 ret = WinHttpCloseHandle( req->request );
885 ok(ret, "WinHttpCloseHandle failed: %u\n", GetLastError());
886 ret = WinHttpCloseHandle( req->connection );
887 ok(ret, "WinHttpCloseHandle failed: %u\n", GetLastError());
888 ret = WinHttpCloseHandle( req->session );
889 ok(ret, "WinHttpCloseHandle failed: %u\n", GetLastError());
891 WaitForSingleObject( info->wait, INFINITE );
892 end_test( info, __LINE__ );
895 static const struct notification read_test[] =
897 { winhttp_read_data, WINHTTP_CALLBACK_STATUS_RECEIVING_RESPONSE, NF_ALLOW },
898 { winhttp_read_data, WINHTTP_CALLBACK_STATUS_RESPONSE_RECEIVED, NF_ALLOW },
899 { winhttp_read_data, WINHTTP_CALLBACK_STATUS_READ_COMPLETE, NF_SIGNAL }
902 static const struct notification read_allow_close_test[] =
904 { winhttp_read_data, WINHTTP_CALLBACK_STATUS_RECEIVING_RESPONSE, NF_ALLOW },
905 { winhttp_read_data, WINHTTP_CALLBACK_STATUS_RESPONSE_RECEIVED, NF_ALLOW },
906 { winhttp_read_data, WINHTTP_CALLBACK_STATUS_CLOSING_CONNECTION, NF_ALLOW },
907 { winhttp_read_data, WINHTTP_CALLBACK_STATUS_CONNECTION_CLOSED, NF_ALLOW },
908 { winhttp_read_data, WINHTTP_CALLBACK_STATUS_READ_COMPLETE, NF_SIGNAL }
911 #define read_request_data(a,b,c,d) _read_request_data(a,b,c,d,__LINE__)
912 static void _read_request_data(struct test_request *req, struct info *info, const char *expected_data, BOOL closing_connection, unsigned line)
914 char buffer[1024];
915 DWORD len;
916 BOOL ret;
918 if (closing_connection)
920 info->test = read_allow_close_test;
921 info->count = ARRAY_SIZE( read_allow_close_test );
923 else
925 info->test = read_test;
926 info->count = ARRAY_SIZE( read_test );
928 info->index = 0;
930 setup_test( info, winhttp_read_data, line );
931 memset(buffer, '?', sizeof(buffer));
932 ret = WinHttpReadData( req->request, buffer, sizeof(buffer), NULL );
933 ok(ret, "failed to read data %u\n", GetLastError());
935 WaitForSingleObject( info->wait, INFINITE );
937 len = strlen(expected_data);
938 ok(!memcmp(buffer, expected_data, len), "unexpected data\n");
941 static void test_persistent_connection(int port)
943 struct test_request req;
944 struct info info;
946 trace("Testing persistent connection...\n");
948 info.wait = CreateEventW( NULL, FALSE, FALSE, NULL );
950 open_socket_request( port, &req, &info );
951 server_send_reply( &req, &info,
952 "HTTP/1.1 200 OK\r\n"
953 "Server: winetest\r\n"
954 "Connection: keep-alive\r\n"
955 "Content-Length: 1\r\n"
956 "\r\n"
957 "X" );
958 read_request_data( &req, &info, "X", FALSE );
959 close_request( &req, &info, FALSE );
961 /* chunked connection test */
962 open_async_request( port, &req, &info, L"/test", TRUE );
963 server_read_data( "GET /test HTTP/1.1\r\n" );
964 server_send_reply( &req, &info,
965 "HTTP/1.1 200 OK\r\n"
966 "Server: winetest\r\n"
967 "Transfer-Encoding: chunked\r\n"
968 "Connection: keep-alive\r\n"
969 "\r\n"
970 "9\r\n123456789\r\n"
971 "0\r\n\r\n" );
972 read_request_data( &req, &info, "123456789", FALSE );
973 close_request( &req, &info, FALSE );
975 /* HTTP/1.1 connections are persistent by default, no additional header is needed */
976 open_async_request( port, &req, &info, L"/test", TRUE );
977 server_read_data( "GET /test HTTP/1.1\r\n" );
978 server_send_reply( &req, &info,
979 "HTTP/1.1 200 OK\r\n"
980 "Server: winetest\r\n"
981 "Content-Length: 2\r\n"
982 "\r\n"
983 "xx" );
984 read_request_data( &req, &info, "xx", FALSE );
985 close_request( &req, &info, FALSE );
987 open_async_request( port, &req, &info, L"/test", TRUE );
988 server_read_data( "GET /test HTTP/1.1\r\n" );
989 server_send_reply( &req, &info,
990 "HTTP/1.1 200 OK\r\n"
991 "Server: winetest\r\n"
992 "Content-Length: 2\r\n"
993 "Connection: close\r\n"
994 "\r\n"
995 "yy" );
996 close_request( &req, &info, TRUE );
998 SetEvent( server_socket_done );
999 CloseHandle( info.wait );
1002 START_TEST (notification)
1004 struct server_info si;
1005 HANDLE thread;
1006 DWORD ret;
1008 test_connection_cache();
1009 test_redirect();
1010 test_async();
1012 si.event = CreateEventW( NULL, 0, 0, NULL );
1013 si.port = 7533;
1015 thread = CreateThread( NULL, 0, server_thread, &si, 0, NULL );
1016 ok(thread != NULL, "failed to create thread %u\n", GetLastError());
1018 server_socket_available = CreateEventW( NULL, 0, 0, NULL );
1019 server_socket_done = CreateEventW( NULL, 0, 0, NULL );
1021 ret = WaitForSingleObject( si.event, 10000 );
1022 ok(ret == WAIT_OBJECT_0, "failed to start winhttp test server %u\n", GetLastError());
1023 if (ret != WAIT_OBJECT_0)
1025 CloseHandle(thread);
1026 return;
1029 test_persistent_connection( si.port );
1031 /* send the basic request again to shutdown the server thread */
1032 test_basic_request( si.port, NULL, L"/quit" );
1034 WaitForSingleObject( thread, 3000 );
1035 CloseHandle( thread );
1036 CloseHandle( server_socket_available );
1037 CloseHandle( server_socket_done );