e14af6d03ea3b8c83aab2f59a234e11044fe2bab
[reactos.git] / rostests / winetests / winhttp / notification.c
1 /*
2 * test status notifications
3 *
4 * Copyright 2008 Hans Leidekker for CodeWeavers
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., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
19 */
20
21 #include <stdarg.h>
22 #include <stdlib.h>
23 #include <windef.h>
24 #include <winbase.h>
25 #include <winhttp.h>
26
27 #include "wine/test.h"
28
29 static const WCHAR user_agent[] = {'w','i','n','e','t','e','s','t',0};
30 static const WCHAR test_winehq[] = {'t','e','s','t','.','w','i','n','e','h','q','.','o','r','g',0};
31
32 enum api
33 {
34 winhttp_connect = 1,
35 winhttp_open_request,
36 winhttp_send_request,
37 winhttp_receive_response,
38 winhttp_query_data,
39 winhttp_read_data,
40 winhttp_write_data,
41 winhttp_close_handle
42 };
43
44 struct notification
45 {
46 enum api function; /* api responsible for notification */
47 unsigned int status; /* status received */
48 BOOL todo;
49 BOOL ignore;
50 BOOL skipped_for_proxy;
51 };
52
53 struct info
54 {
55 enum api function;
56 const struct notification *test;
57 unsigned int count;
58 unsigned int index;
59 HANDLE wait;
60 unsigned int line;
61 };
62
63 static BOOL proxy_active(void)
64 {
65 WINHTTP_PROXY_INFO proxy_info;
66 BOOL active = FALSE;
67
68 if (WinHttpGetDefaultProxyConfiguration(&proxy_info))
69 {
70 active = (proxy_info.lpszProxy != NULL);
71 if (active)
72 GlobalFree(proxy_info.lpszProxy);
73 if (proxy_info.lpszProxyBypass != NULL)
74 GlobalFree(proxy_info.lpszProxyBypass);
75 }
76 else
77 active = FALSE;
78
79 return active;
80 }
81
82 static void CALLBACK check_notification( HINTERNET handle, DWORD_PTR context, DWORD status, LPVOID buffer, DWORD buflen )
83 {
84 BOOL status_ok, function_ok;
85 struct info *info = (struct info *)context;
86 unsigned int i = info->index;
87
88 if (status == WINHTTP_CALLBACK_STATUS_HANDLE_CREATED)
89 {
90 DWORD size = sizeof(struct info *);
91 WinHttpQueryOption( handle, WINHTTP_OPTION_CONTEXT_VALUE, &info, &size );
92 }
93 ok(i < info->count, "%u: unexpected notification 0x%08x\n", info->line, status);
94 if (i >= info->count) return;
95
96 status_ok = (info->test[i].status == status);
97 function_ok = (info->test[i].function == info->function);
98 if (!info->test[i].ignore && !info->test[i].todo)
99 {
100 ok(status_ok, "%u: expected status 0x%08x got 0x%08x\n", info->line, info->test[i].status, status);
101 ok(function_ok, "%u: expected function %u got %u\n", info->line, info->test[i].function, info->function);
102 }
103 else if (!info->test[i].ignore)
104 {
105 todo_wine ok(status_ok, "%u: expected status 0x%08x got 0x%08x\n", info->line, info->test[i].status, status);
106 if (status_ok)
107 {
108 todo_wine ok(function_ok, "%u: expected function %u got %u\n", info->line, info->test[i].function, info->function);
109 }
110 }
111 if (status_ok && function_ok) info->index++;
112 if (proxy_active())
113 {
114 while (info->test[info->index].skipped_for_proxy)
115 info->index++;
116 }
117
118 if (status & (WINHTTP_CALLBACK_FLAG_ALL_COMPLETIONS | WINHTTP_CALLBACK_STATUS_HANDLE_CLOSING))
119 {
120 SetEvent( info->wait );
121 }
122 }
123
124 static const struct notification cache_test[] =
125 {
126 { winhttp_connect, WINHTTP_CALLBACK_STATUS_HANDLE_CREATED },
127 { winhttp_open_request, WINHTTP_CALLBACK_STATUS_HANDLE_CREATED },
128 { winhttp_send_request, WINHTTP_CALLBACK_STATUS_RESOLVING_NAME },
129 { winhttp_send_request, WINHTTP_CALLBACK_STATUS_NAME_RESOLVED },
130 { winhttp_send_request, WINHTTP_CALLBACK_STATUS_CONNECTING_TO_SERVER },
131 { winhttp_send_request, WINHTTP_CALLBACK_STATUS_CONNECTED_TO_SERVER },
132 { winhttp_send_request, WINHTTP_CALLBACK_STATUS_SENDING_REQUEST },
133 { winhttp_send_request, WINHTTP_CALLBACK_STATUS_REQUEST_SENT },
134 { winhttp_receive_response, WINHTTP_CALLBACK_STATUS_RECEIVING_RESPONSE },
135 { winhttp_receive_response, WINHTTP_CALLBACK_STATUS_RESPONSE_RECEIVED },
136 { winhttp_close_handle, WINHTTP_CALLBACK_STATUS_CLOSING_CONNECTION, FALSE, TRUE },
137 { winhttp_close_handle, WINHTTP_CALLBACK_STATUS_CONNECTION_CLOSED, FALSE, TRUE },
138 { winhttp_close_handle, WINHTTP_CALLBACK_STATUS_HANDLE_CLOSING, FALSE, TRUE },
139 { winhttp_open_request, WINHTTP_CALLBACK_STATUS_HANDLE_CREATED },
140 { winhttp_send_request, WINHTTP_CALLBACK_STATUS_CONNECTING_TO_SERVER },
141 { winhttp_send_request, WINHTTP_CALLBACK_STATUS_CONNECTED_TO_SERVER },
142 { winhttp_send_request, WINHTTP_CALLBACK_STATUS_SENDING_REQUEST },
143 { winhttp_send_request, WINHTTP_CALLBACK_STATUS_REQUEST_SENT },
144 { winhttp_receive_response, WINHTTP_CALLBACK_STATUS_RECEIVING_RESPONSE },
145 { winhttp_receive_response, WINHTTP_CALLBACK_STATUS_RESPONSE_RECEIVED },
146 { winhttp_close_handle, WINHTTP_CALLBACK_STATUS_CLOSING_CONNECTION, FALSE, TRUE },
147 { winhttp_close_handle, WINHTTP_CALLBACK_STATUS_CONNECTION_CLOSED, FALSE, TRUE },
148 { winhttp_close_handle, WINHTTP_CALLBACK_STATUS_HANDLE_CLOSING, FALSE, TRUE },
149 { winhttp_close_handle, WINHTTP_CALLBACK_STATUS_HANDLE_CLOSING, TRUE, TRUE },
150 { winhttp_close_handle, WINHTTP_CALLBACK_STATUS_HANDLE_CLOSING, TRUE, TRUE }
151 };
152
153 static void setup_test( struct info *info, enum api function, unsigned int line )
154 {
155 info->function = function;
156 info->line = line;
157 }
158
159 static void test_connection_cache( void )
160 {
161 HANDLE ses, con, req;
162 DWORD size, status;
163 BOOL ret;
164 struct info info, *context = &info;
165
166 info.test = cache_test;
167 info.count = sizeof(cache_test) / sizeof(cache_test[0]);
168 info.index = 0;
169 info.wait = NULL;
170
171 ses = WinHttpOpen( user_agent, 0, NULL, NULL, 0 );
172 ok(ses != NULL, "failed to open session %u\n", GetLastError());
173
174 WinHttpSetStatusCallback( ses, check_notification, WINHTTP_CALLBACK_FLAG_ALL_NOTIFICATIONS, 0 );
175
176 ret = WinHttpSetOption( ses, WINHTTP_OPTION_CONTEXT_VALUE, &context, sizeof(struct info *) );
177 ok(ret, "failed to set context value %u\n", GetLastError());
178
179 setup_test( &info, winhttp_connect, __LINE__ );
180 con = WinHttpConnect( ses, test_winehq, 0, 0 );
181 ok(con != NULL, "failed to open a connection %u\n", GetLastError());
182
183 setup_test( &info, winhttp_open_request, __LINE__ );
184 req = WinHttpOpenRequest( con, NULL, NULL, NULL, NULL, NULL, 0 );
185 ok(req != NULL, "failed to open a request %u\n", GetLastError());
186
187 setup_test( &info, winhttp_send_request, __LINE__ );
188 ret = WinHttpSendRequest( req, NULL, 0, NULL, 0, 0, 0 );
189 if (!ret && GetLastError() == ERROR_WINHTTP_CANNOT_CONNECT)
190 {
191 skip("connection failed, skipping\n");
192 goto done;
193 }
194 ok(ret, "failed to send request %u\n", GetLastError());
195
196 setup_test( &info, winhttp_receive_response, __LINE__ );
197 ret = WinHttpReceiveResponse( req, NULL );
198 ok(ret, "failed to receive response %u\n", GetLastError());
199
200 size = sizeof(status);
201 ret = WinHttpQueryHeaders( req, WINHTTP_QUERY_STATUS_CODE | WINHTTP_QUERY_FLAG_NUMBER, NULL, &status, &size, NULL );
202 ok(ret, "failed unexpectedly %u\n", GetLastError());
203 ok(status == 200, "request failed unexpectedly %u\n", status);
204
205 setup_test( &info, winhttp_close_handle, __LINE__ );
206 WinHttpCloseHandle( req );
207
208 setup_test( &info, winhttp_open_request, __LINE__ );
209 req = WinHttpOpenRequest( con, NULL, NULL, NULL, NULL, NULL, 0 );
210 ok(req != NULL, "failed to open a request %u\n", GetLastError());
211
212 ret = WinHttpSetOption( req, WINHTTP_OPTION_CONTEXT_VALUE, &context, sizeof(struct info *) );
213 ok(ret, "failed to set context value %u\n", GetLastError());
214
215 setup_test( &info, winhttp_send_request, __LINE__ );
216 ret = WinHttpSendRequest( req, NULL, 0, NULL, 0, 0, 0 );
217 if (!ret && GetLastError() == ERROR_WINHTTP_CANNOT_CONNECT)
218 {
219 skip("connection failed, skipping\n");
220 goto done;
221 }
222 ok(ret, "failed to send request %u\n", GetLastError());
223
224 setup_test( &info, winhttp_receive_response, __LINE__ );
225 ret = WinHttpReceiveResponse( req, NULL );
226 ok(ret, "failed to receive response %u\n", GetLastError());
227
228 size = sizeof(status);
229 ret = WinHttpQueryHeaders( req, WINHTTP_QUERY_STATUS_CODE | WINHTTP_QUERY_FLAG_NUMBER, NULL, &status, &size, NULL );
230 ok(ret, "failed unexpectedly %u\n", GetLastError());
231 ok(status == 200, "request failed unexpectedly %u\n", status);
232
233 setup_test( &info, winhttp_close_handle, __LINE__ );
234 WinHttpCloseHandle( req );
235
236 setup_test( &info, winhttp_close_handle, __LINE__ );
237 WinHttpCloseHandle( req );
238 WinHttpCloseHandle( con );
239 WinHttpCloseHandle( ses );
240
241 Sleep(2000); /* make sure connection is evicted from cache */
242
243 info.index = 0;
244
245 ses = WinHttpOpen( user_agent, 0, NULL, NULL, 0 );
246 ok(ses != NULL, "failed to open session %u\n", GetLastError());
247
248 WinHttpSetStatusCallback( ses, check_notification, WINHTTP_CALLBACK_FLAG_ALL_NOTIFICATIONS, 0 );
249
250 ret = WinHttpSetOption( ses, WINHTTP_OPTION_CONTEXT_VALUE, &context, sizeof(struct info *) );
251 ok(ret, "failed to set context value %u\n", GetLastError());
252
253 setup_test( &info, winhttp_connect, __LINE__ );
254 con = WinHttpConnect( ses, test_winehq, 0, 0 );
255 ok(con != NULL, "failed to open a connection %u\n", GetLastError());
256
257 setup_test( &info, winhttp_open_request, __LINE__ );
258 req = WinHttpOpenRequest( con, NULL, NULL, NULL, NULL, NULL, 0 );
259 ok(req != NULL, "failed to open a request %u\n", GetLastError());
260
261 ret = WinHttpSetOption( req, WINHTTP_OPTION_CONTEXT_VALUE, &context, sizeof(struct info *) );
262 ok(ret, "failed to set context value %u\n", GetLastError());
263
264 setup_test( &info, winhttp_send_request, __LINE__ );
265 ret = WinHttpSendRequest( req, NULL, 0, NULL, 0, 0, 0 );
266 if (!ret && GetLastError() == ERROR_WINHTTP_CANNOT_CONNECT)
267 {
268 skip("connection failed, skipping\n");
269 goto done;
270 }
271 ok(ret, "failed to send request %u\n", GetLastError());
272
273 setup_test( &info, winhttp_receive_response, __LINE__ );
274 ret = WinHttpReceiveResponse( req, NULL );
275 ok(ret, "failed to receive response %u\n", GetLastError());
276
277 size = sizeof(status);
278 ret = WinHttpQueryHeaders( req, WINHTTP_QUERY_STATUS_CODE | WINHTTP_QUERY_FLAG_NUMBER, NULL, &status, &size, NULL );
279 ok(ret, "failed unexpectedly %u\n", GetLastError());
280 ok(status == 200, "request failed unexpectedly %u\n", status);
281
282 setup_test( &info, winhttp_close_handle, __LINE__ );
283 WinHttpCloseHandle( req );
284
285 setup_test( &info, winhttp_open_request, __LINE__ );
286 req = WinHttpOpenRequest( con, NULL, NULL, NULL, NULL, NULL, 0 );
287 ok(req != NULL, "failed to open a request %u\n", GetLastError());
288
289 ret = WinHttpSetOption( req, WINHTTP_OPTION_CONTEXT_VALUE, &context, sizeof(struct info *) );
290 ok(ret, "failed to set context value %u\n", GetLastError());
291
292 setup_test( &info, winhttp_send_request, __LINE__ );
293 ret = WinHttpSendRequest( req, NULL, 0, NULL, 0, 0, 0 );
294 if (!ret && GetLastError() == ERROR_WINHTTP_CANNOT_CONNECT)
295 {
296 skip("connection failed, skipping\n");
297 goto done;
298 }
299 ok(ret, "failed to send request %u\n", GetLastError());
300
301 setup_test( &info, winhttp_receive_response, __LINE__ );
302 ret = WinHttpReceiveResponse( req, NULL );
303 ok(ret, "failed to receive response %u\n", GetLastError());
304
305 size = sizeof(status);
306 ret = WinHttpQueryHeaders( req, WINHTTP_QUERY_STATUS_CODE | WINHTTP_QUERY_FLAG_NUMBER, NULL, &status, &size, NULL );
307 ok(ret, "failed unexpectedly %u\n", GetLastError());
308 ok(status == 200, "request failed unexpectedly %u\n", status);
309
310 setup_test( &info, winhttp_close_handle, __LINE__ );
311 done:
312 WinHttpCloseHandle( req );
313 WinHttpCloseHandle( con );
314 WinHttpCloseHandle( ses );
315
316 Sleep(2000); /* make sure connection is evicted from cache */
317 }
318
319 static const struct notification redirect_test[] =
320 {
321 { winhttp_connect, WINHTTP_CALLBACK_STATUS_HANDLE_CREATED },
322 { winhttp_open_request, WINHTTP_CALLBACK_STATUS_HANDLE_CREATED },
323 { winhttp_send_request, WINHTTP_CALLBACK_STATUS_RESOLVING_NAME, FALSE, TRUE },
324 { winhttp_send_request, WINHTTP_CALLBACK_STATUS_NAME_RESOLVED, FALSE, TRUE },
325 { winhttp_send_request, WINHTTP_CALLBACK_STATUS_CONNECTING_TO_SERVER },
326 { winhttp_send_request, WINHTTP_CALLBACK_STATUS_CONNECTED_TO_SERVER },
327 { winhttp_send_request, WINHTTP_CALLBACK_STATUS_SENDING_REQUEST },
328 { winhttp_send_request, WINHTTP_CALLBACK_STATUS_REQUEST_SENT },
329 { winhttp_receive_response, WINHTTP_CALLBACK_STATUS_RECEIVING_RESPONSE },
330 { winhttp_receive_response, WINHTTP_CALLBACK_STATUS_RESPONSE_RECEIVED },
331 { winhttp_receive_response, WINHTTP_CALLBACK_STATUS_REDIRECT },
332 { winhttp_receive_response, WINHTTP_CALLBACK_STATUS_RESOLVING_NAME, FALSE, TRUE, TRUE },
333 { winhttp_receive_response, WINHTTP_CALLBACK_STATUS_NAME_RESOLVED, FALSE, TRUE, TRUE },
334 { winhttp_receive_response, WINHTTP_CALLBACK_STATUS_CONNECTING_TO_SERVER, FALSE, FALSE, TRUE },
335 { winhttp_receive_response, WINHTTP_CALLBACK_STATUS_CONNECTED_TO_SERVER, FALSE, FALSE, TRUE },
336 { winhttp_receive_response, WINHTTP_CALLBACK_STATUS_SENDING_REQUEST },
337 { winhttp_receive_response, WINHTTP_CALLBACK_STATUS_REQUEST_SENT },
338 { winhttp_receive_response, WINHTTP_CALLBACK_STATUS_RECEIVING_RESPONSE },
339 { winhttp_receive_response, WINHTTP_CALLBACK_STATUS_RESPONSE_RECEIVED },
340 { winhttp_close_handle, WINHTTP_CALLBACK_STATUS_CLOSING_CONNECTION, FALSE, TRUE },
341 { winhttp_close_handle, WINHTTP_CALLBACK_STATUS_CONNECTION_CLOSED, FALSE, TRUE },
342 { winhttp_close_handle, WINHTTP_CALLBACK_STATUS_HANDLE_CLOSING, FALSE, TRUE },
343 { winhttp_close_handle, WINHTTP_CALLBACK_STATUS_HANDLE_CLOSING, TRUE, TRUE },
344 { winhttp_close_handle, WINHTTP_CALLBACK_STATUS_HANDLE_CLOSING, TRUE, TRUE }
345 };
346
347 static void test_redirect( void )
348 {
349 HANDLE ses, con, req;
350 DWORD size, status;
351 BOOL ret;
352 struct info info, *context = &info;
353
354 info.test = redirect_test;
355 info.count = sizeof(redirect_test) / sizeof(redirect_test[0]);
356 info.index = 0;
357 info.wait = NULL;
358
359 ses = WinHttpOpen( user_agent, 0, NULL, NULL, 0 );
360 ok(ses != NULL, "failed to open session %u\n", GetLastError());
361
362 WinHttpSetStatusCallback( ses, check_notification, WINHTTP_CALLBACK_FLAG_ALL_NOTIFICATIONS, 0 );
363
364 ret = WinHttpSetOption( ses, WINHTTP_OPTION_CONTEXT_VALUE, &context, sizeof(struct info *) );
365 ok(ret, "failed to set context value %u\n", GetLastError());
366
367 setup_test( &info, winhttp_connect, __LINE__ );
368 con = WinHttpConnect( ses, test_winehq, 0, 0 );
369 ok(con != NULL, "failed to open a connection %u\n", GetLastError());
370
371 setup_test( &info, winhttp_open_request, __LINE__ );
372 req = WinHttpOpenRequest( con, NULL, NULL, NULL, NULL, NULL, 0 );
373 ok(req != NULL, "failed to open a request %u\n", GetLastError());
374
375 setup_test( &info, winhttp_send_request, __LINE__ );
376 ret = WinHttpSendRequest( req, NULL, 0, NULL, 0, 0, 0 );
377 if (!ret && GetLastError() == ERROR_WINHTTP_CANNOT_CONNECT)
378 {
379 skip("connection failed, skipping\n");
380 goto done;
381 }
382 ok(ret, "failed to send request %u\n", GetLastError());
383
384 setup_test( &info, winhttp_receive_response, __LINE__ );
385 ret = WinHttpReceiveResponse( req, NULL );
386 ok(ret, "failed to receive response %u\n", GetLastError());
387
388 size = sizeof(status);
389 ret = WinHttpQueryHeaders( req, WINHTTP_QUERY_STATUS_CODE | WINHTTP_QUERY_FLAG_NUMBER, NULL, &status, &size, NULL );
390 ok(ret, "failed unexpectedly %u\n", GetLastError());
391 ok(status == 200, "request failed unexpectedly %u\n", status);
392
393 setup_test( &info, winhttp_close_handle, __LINE__ );
394 done:
395 WinHttpCloseHandle( req );
396 WinHttpCloseHandle( con );
397 WinHttpCloseHandle( ses );
398 }
399
400 static const struct notification async_test[] =
401 {
402 { winhttp_connect, WINHTTP_CALLBACK_STATUS_HANDLE_CREATED },
403 { winhttp_open_request, WINHTTP_CALLBACK_STATUS_HANDLE_CREATED },
404 { winhttp_send_request, WINHTTP_CALLBACK_STATUS_RESOLVING_NAME, FALSE, TRUE },
405 { winhttp_send_request, WINHTTP_CALLBACK_STATUS_NAME_RESOLVED, FALSE, TRUE },
406 { winhttp_send_request, WINHTTP_CALLBACK_STATUS_CONNECTING_TO_SERVER },
407 { winhttp_send_request, WINHTTP_CALLBACK_STATUS_CONNECTED_TO_SERVER },
408 { winhttp_send_request, WINHTTP_CALLBACK_STATUS_SENDING_REQUEST },
409 { winhttp_send_request, WINHTTP_CALLBACK_STATUS_REQUEST_SENT },
410 { winhttp_send_request, WINHTTP_CALLBACK_STATUS_SENDREQUEST_COMPLETE },
411 { winhttp_receive_response, WINHTTP_CALLBACK_STATUS_RECEIVING_RESPONSE },
412 { winhttp_receive_response, WINHTTP_CALLBACK_STATUS_RESPONSE_RECEIVED },
413 { winhttp_receive_response, WINHTTP_CALLBACK_STATUS_REDIRECT },
414 { winhttp_receive_response, WINHTTP_CALLBACK_STATUS_RESOLVING_NAME, FALSE, TRUE, TRUE },
415 { winhttp_receive_response, WINHTTP_CALLBACK_STATUS_NAME_RESOLVED, FALSE, TRUE, TRUE },
416 { winhttp_receive_response, WINHTTP_CALLBACK_STATUS_CONNECTING_TO_SERVER, FALSE, FALSE, TRUE },
417 { winhttp_receive_response, WINHTTP_CALLBACK_STATUS_CONNECTED_TO_SERVER, FALSE, FALSE, TRUE },
418 { winhttp_receive_response, WINHTTP_CALLBACK_STATUS_SENDING_REQUEST },
419 { winhttp_receive_response, WINHTTP_CALLBACK_STATUS_REQUEST_SENT },
420 { winhttp_receive_response, WINHTTP_CALLBACK_STATUS_RECEIVING_RESPONSE },
421 { winhttp_receive_response, WINHTTP_CALLBACK_STATUS_RESPONSE_RECEIVED },
422 { winhttp_receive_response, WINHTTP_CALLBACK_STATUS_HEADERS_AVAILABLE },
423 { winhttp_query_data, WINHTTP_CALLBACK_STATUS_DATA_AVAILABLE },
424 { winhttp_read_data, WINHTTP_CALLBACK_STATUS_RECEIVING_RESPONSE, FALSE, TRUE },
425 { winhttp_read_data, WINHTTP_CALLBACK_STATUS_RESPONSE_RECEIVED, FALSE, TRUE },
426 { winhttp_read_data, WINHTTP_CALLBACK_STATUS_READ_COMPLETE, FALSE, TRUE },
427 { winhttp_close_handle, WINHTTP_CALLBACK_STATUS_CLOSING_CONNECTION, FALSE, TRUE },
428 { winhttp_close_handle, WINHTTP_CALLBACK_STATUS_CONNECTION_CLOSED, FALSE, TRUE },
429 { winhttp_close_handle, WINHTTP_CALLBACK_STATUS_HANDLE_CLOSING, FALSE, TRUE },
430 { winhttp_close_handle, WINHTTP_CALLBACK_STATUS_HANDLE_CLOSING, TRUE, TRUE },
431 { winhttp_close_handle, WINHTTP_CALLBACK_STATUS_HANDLE_CLOSING, TRUE, TRUE }
432 };
433
434 static void test_async( void )
435 {
436 HANDLE ses, con, req;
437 DWORD size, status;
438 BOOL ret;
439 struct info info, *context = &info;
440 char buffer[1024];
441
442 info.test = async_test;
443 info.count = sizeof(async_test) / sizeof(async_test[0]);
444 info.index = 0;
445 info.wait = CreateEventW( NULL, FALSE, FALSE, NULL );
446
447 ses = WinHttpOpen( user_agent, 0, NULL, NULL, WINHTTP_FLAG_ASYNC );
448 ok(ses != NULL, "failed to open session %u\n", GetLastError());
449
450 WinHttpSetStatusCallback( ses, check_notification, WINHTTP_CALLBACK_FLAG_ALL_NOTIFICATIONS, 0 );
451
452 ret = WinHttpSetOption( ses, WINHTTP_OPTION_CONTEXT_VALUE, &context, sizeof(struct info *) );
453 ok(ret, "failed to set context value %u\n", GetLastError());
454
455 setup_test( &info, winhttp_connect, __LINE__ );
456 con = WinHttpConnect( ses, test_winehq, 0, 0 );
457 ok(con != NULL, "failed to open a connection %u\n", GetLastError());
458
459 setup_test( &info, winhttp_open_request, __LINE__ );
460 req = WinHttpOpenRequest( con, NULL, NULL, NULL, NULL, NULL, 0 );
461 ok(req != NULL, "failed to open a request %u\n", GetLastError());
462
463 setup_test( &info, winhttp_send_request, __LINE__ );
464 ret = WinHttpSendRequest( req, NULL, 0, NULL, 0, 0, 0 );
465 if (!ret && GetLastError() == ERROR_WINHTTP_CANNOT_CONNECT)
466 {
467 skip("connection failed, skipping\n");
468 WinHttpCloseHandle( req );
469 WinHttpCloseHandle( con );
470 WinHttpCloseHandle( ses );
471 CloseHandle( info.wait );
472 return;
473 }
474 ok(ret, "failed to send request %u\n", GetLastError());
475
476 WaitForSingleObject( info.wait, INFINITE );
477
478 setup_test( &info, winhttp_receive_response, __LINE__ );
479 ret = WinHttpReceiveResponse( req, NULL );
480 ok(ret, "failed to receive response %u\n", GetLastError());
481
482 WaitForSingleObject( info.wait, INFINITE );
483
484 size = sizeof(status);
485 ret = WinHttpQueryHeaders( req, WINHTTP_QUERY_STATUS_CODE | WINHTTP_QUERY_FLAG_NUMBER, NULL, &status, &size, NULL );
486 ok(ret, "failed unexpectedly %u\n", GetLastError());
487 ok(status == 200, "request failed unexpectedly %u\n", status);
488
489 setup_test( &info, winhttp_query_data, __LINE__ );
490 ret = WinHttpQueryDataAvailable( req, NULL );
491 ok(ret, "failed to query data available %u\n", GetLastError());
492
493 WaitForSingleObject( info.wait, INFINITE );
494
495 setup_test( &info, winhttp_read_data, __LINE__ );
496 ret = WinHttpReadData( req, buffer, sizeof(buffer), NULL );
497 ok(ret, "failed to query data available %u\n", GetLastError());
498
499 WaitForSingleObject( info.wait, INFINITE );
500
501 setup_test( &info, winhttp_close_handle, __LINE__ );
502 WinHttpCloseHandle( req );
503 WinHttpCloseHandle( con );
504 WinHttpCloseHandle( ses );
505
506 WaitForSingleObject( info.wait, INFINITE );
507 CloseHandle( info.wait );
508 }
509
510 START_TEST (notification)
511 {
512 test_connection_cache();
513 test_redirect();
514 Sleep(2000); /* make sure previous connection is evicted from cache */
515 test_async();
516 }