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
27 #include "wine/test.h"
29 static const WCHAR user_agent
[] = {'w','i','n','e','t','e','s','t',0};
36 winhttp_receive_response
,
45 enum api function
; /* api responsible for notification */
46 unsigned int status
; /* status received */
49 int skipped_for_proxy
;
55 const struct notification
*test
;
62 static BOOL
proxy_active(void)
64 WINHTTP_PROXY_INFO proxy_info
;
67 if (WinHttpGetDefaultProxyConfiguration(&proxy_info
))
69 active
= (proxy_info
.lpszProxy
!= NULL
);
71 GlobalFree((HGLOBAL
) proxy_info
.lpszProxy
);
72 if (proxy_info
.lpszProxyBypass
!= NULL
)
73 GlobalFree((HGLOBAL
) proxy_info
.lpszProxyBypass
);
81 static void CALLBACK
check_notification( HINTERNET handle
, DWORD_PTR context
, DWORD status
, LPVOID buffer
, DWORD buflen
)
83 BOOL status_ok
, function_ok
;
84 struct info
*info
= (struct info
*)context
;
85 unsigned int i
= info
->index
;
87 if (status
== WINHTTP_CALLBACK_STATUS_HANDLE_CREATED
)
89 DWORD size
= sizeof(struct info
*);
90 WinHttpQueryOption( handle
, WINHTTP_OPTION_CONTEXT_VALUE
, &info
, &size
);
92 ok(i
< info
->count
, "unexpected notification 0x%08x\n", status
);
93 if (i
>= info
->count
) return;
95 status_ok
= (info
->test
[i
].status
== status
);
96 function_ok
= (info
->test
[i
].function
== info
->function
);
97 if (!info
->test
[i
].ignore
&& !info
->test
[i
].todo
)
99 ok(status_ok
, "%u: expected status 0x%08x got 0x%08x\n", info
->line
, info
->test
[i
].status
, status
);
100 ok(function_ok
, "%u: expected function %u got %u\n", info
->line
, info
->test
[i
].function
, info
->function
);
102 else if (!info
->test
[i
].ignore
)
104 todo_wine
ok(status_ok
, "%u: expected status 0x%08x got 0x%08x\n", info
->line
, info
->test
[i
].status
, status
);
107 todo_wine
ok(function_ok
, "%u: expected function %u got %u\n", info
->line
, info
->test
[i
].function
, info
->function
);
110 if (status_ok
) info
->index
++;
113 while (info
->test
[info
->index
].skipped_for_proxy
)
117 if (status
& (WINHTTP_CALLBACK_FLAG_ALL_COMPLETIONS
| WINHTTP_CALLBACK_STATUS_HANDLE_CLOSING
))
119 SetEvent( info
->wait
);
123 static const struct notification cache_test
[] =
125 { winhttp_connect
, WINHTTP_CALLBACK_STATUS_HANDLE_CREATED
, 0 },
126 { winhttp_open_request
, WINHTTP_CALLBACK_STATUS_HANDLE_CREATED
, 0 },
127 { winhttp_send_request
, WINHTTP_CALLBACK_STATUS_RESOLVING_NAME
, 0 },
128 { winhttp_send_request
, WINHTTP_CALLBACK_STATUS_NAME_RESOLVED
, 0 },
129 { winhttp_send_request
, WINHTTP_CALLBACK_STATUS_CONNECTING_TO_SERVER
, 0 },
130 { winhttp_send_request
, WINHTTP_CALLBACK_STATUS_CONNECTED_TO_SERVER
, 0 },
131 { winhttp_send_request
, WINHTTP_CALLBACK_STATUS_SENDING_REQUEST
, 0 },
132 { winhttp_send_request
, WINHTTP_CALLBACK_STATUS_REQUEST_SENT
, 0 },
133 { winhttp_receive_response
, WINHTTP_CALLBACK_STATUS_RECEIVING_RESPONSE
, 0 },
134 { winhttp_receive_response
, WINHTTP_CALLBACK_STATUS_RESPONSE_RECEIVED
, 0 },
135 { winhttp_close_handle
, WINHTTP_CALLBACK_STATUS_CLOSING_CONNECTION
, 0, 1 },
136 { winhttp_close_handle
, WINHTTP_CALLBACK_STATUS_CONNECTION_CLOSED
, 0, 1 },
137 { winhttp_close_handle
, WINHTTP_CALLBACK_STATUS_HANDLE_CLOSING
, 0, 1 },
138 { winhttp_close_handle
, WINHTTP_CALLBACK_STATUS_HANDLE_CLOSING
, 1, 1 },
139 { winhttp_close_handle
, WINHTTP_CALLBACK_STATUS_HANDLE_CLOSING
, 1, 1 }
142 static void setup_test( struct info
*info
, enum api function
, unsigned int line
)
144 info
->function
= function
;
148 static void test_connection_cache( void )
150 static const WCHAR codeweavers
[] = {'w','w','w','.','c','o','d','e','w','e','a','v','e','r','s','.','c','o','m',0};
152 HANDLE ses
, con
, req
;
155 struct info info
, *context
= &info
;
157 info
.test
= cache_test
;
158 info
.count
= sizeof(cache_test
) / sizeof(cache_test
[0]);
162 ses
= WinHttpOpen( user_agent
, 0, NULL
, NULL
, 0 );
163 ok(ses
!= NULL
, "failed to open session %u\n", GetLastError());
165 WinHttpSetStatusCallback( ses
, check_notification
, WINHTTP_CALLBACK_FLAG_ALL_NOTIFICATIONS
, 0 );
167 ret
= WinHttpSetOption( ses
, WINHTTP_OPTION_CONTEXT_VALUE
, &context
, sizeof(struct info
*) );
168 ok(ret
, "failed to set context value %u\n", GetLastError());
170 setup_test( &info
, winhttp_connect
, __LINE__
);
171 con
= WinHttpConnect( ses
, codeweavers
, 0, 0 );
172 ok(con
!= NULL
, "failed to open a connection %u\n", GetLastError());
174 setup_test( &info
, winhttp_open_request
, __LINE__
);
175 req
= WinHttpOpenRequest( con
, NULL
, NULL
, NULL
, NULL
, NULL
, 0 );
176 ok(req
!= NULL
, "failed to open a request %u\n", GetLastError());
178 setup_test( &info
, winhttp_send_request
, __LINE__
);
179 ret
= WinHttpSendRequest( req
, NULL
, 0, NULL
, 0, 0, 0 );
180 ok(ret
, "failed to send request %u\n", GetLastError());
182 setup_test( &info
, winhttp_receive_response
, __LINE__
);
183 ret
= WinHttpReceiveResponse( req
, NULL
);
184 ok(ret
, "failed to receive response %u\n", GetLastError());
186 size
= sizeof(status
);
187 ret
= WinHttpQueryHeaders( req
, WINHTTP_QUERY_STATUS_CODE
| WINHTTP_QUERY_FLAG_NUMBER
, NULL
, &status
, &size
, NULL
);
188 ok(ret
, "failed unexpectedly %u\n", GetLastError());
189 ok(status
== 200, "request failed unexpectedly %u\n", status
);
191 setup_test( &info
, winhttp_close_handle
, __LINE__
);
192 WinHttpCloseHandle( req
);
193 WinHttpCloseHandle( con
);
194 WinHttpCloseHandle( ses
);
196 Sleep(2000); /* make sure connection is evicted from cache */
200 ses
= WinHttpOpen( user_agent
, 0, NULL
, NULL
, 0 );
201 ok(ses
!= NULL
, "failed to open session %u\n", GetLastError());
203 WinHttpSetStatusCallback( ses
, check_notification
, WINHTTP_CALLBACK_FLAG_ALL_NOTIFICATIONS
, 0 );
205 ret
= WinHttpSetOption( ses
, WINHTTP_OPTION_CONTEXT_VALUE
, &context
, sizeof(struct info
*) );
206 ok(ret
, "failed to set context value %u\n", GetLastError());
208 setup_test( &info
, winhttp_connect
, __LINE__
);
209 con
= WinHttpConnect( ses
, codeweavers
, 0, 0 );
210 ok(con
!= NULL
, "failed to open a connection %u\n", GetLastError());
212 setup_test( &info
, winhttp_open_request
, __LINE__
);
213 req
= WinHttpOpenRequest( con
, NULL
, NULL
, NULL
, NULL
, NULL
, 0 );
214 ok(req
!= NULL
, "failed to open a request %u\n", GetLastError());
216 ret
= WinHttpSetOption( req
, WINHTTP_OPTION_CONTEXT_VALUE
, &context
, sizeof(struct info
*) );
217 ok(ret
, "failed to set context value %u\n", GetLastError());
219 setup_test( &info
, winhttp_send_request
, __LINE__
);
220 ret
= WinHttpSendRequest( req
, NULL
, 0, NULL
, 0, 0, 0 );
221 ok(ret
, "failed to send request %u\n", GetLastError());
223 setup_test( &info
, winhttp_receive_response
, __LINE__
);
224 ret
= WinHttpReceiveResponse( req
, NULL
);
225 ok(ret
, "failed to receive response %u\n", GetLastError());
227 size
= sizeof(status
);
228 ret
= WinHttpQueryHeaders( req
, WINHTTP_QUERY_STATUS_CODE
| WINHTTP_QUERY_FLAG_NUMBER
, NULL
, &status
, &size
, NULL
);
229 ok(ret
, "failed unexpectedly %u\n", GetLastError());
230 ok(status
== 200, "request failed unexpectedly %u\n", status
);
232 setup_test( &info
, winhttp_close_handle
, __LINE__
);
233 WinHttpCloseHandle( req
);
234 WinHttpCloseHandle( con
);
235 WinHttpCloseHandle( ses
);
238 static const struct notification redirect_test
[] =
240 { winhttp_connect
, WINHTTP_CALLBACK_STATUS_HANDLE_CREATED
, 0 },
241 { winhttp_open_request
, WINHTTP_CALLBACK_STATUS_HANDLE_CREATED
, 0 },
242 { winhttp_send_request
, WINHTTP_CALLBACK_STATUS_RESOLVING_NAME
, 0 },
243 { winhttp_send_request
, WINHTTP_CALLBACK_STATUS_NAME_RESOLVED
, 0 },
244 { winhttp_send_request
, WINHTTP_CALLBACK_STATUS_CONNECTING_TO_SERVER
, 0 },
245 { winhttp_send_request
, WINHTTP_CALLBACK_STATUS_CONNECTED_TO_SERVER
, 0 },
246 { winhttp_send_request
, WINHTTP_CALLBACK_STATUS_SENDING_REQUEST
, 0 },
247 { winhttp_send_request
, WINHTTP_CALLBACK_STATUS_REQUEST_SENT
, 0 },
248 { winhttp_receive_response
, WINHTTP_CALLBACK_STATUS_RECEIVING_RESPONSE
, 0 },
249 { winhttp_receive_response
, WINHTTP_CALLBACK_STATUS_RESPONSE_RECEIVED
, 0 },
250 { winhttp_receive_response
, WINHTTP_CALLBACK_STATUS_REDIRECT
, 0 },
251 { winhttp_receive_response
, WINHTTP_CALLBACK_STATUS_RESOLVING_NAME
, 0, 0, 1 },
252 { winhttp_receive_response
, WINHTTP_CALLBACK_STATUS_NAME_RESOLVED
, 0, 0, 1 },
253 { winhttp_receive_response
, WINHTTP_CALLBACK_STATUS_CONNECTING_TO_SERVER
, 0, 0, 1 },
254 { winhttp_receive_response
, WINHTTP_CALLBACK_STATUS_CONNECTED_TO_SERVER
, 0, 0, 1 },
255 { winhttp_receive_response
, WINHTTP_CALLBACK_STATUS_SENDING_REQUEST
, 0 },
256 { winhttp_receive_response
, WINHTTP_CALLBACK_STATUS_REQUEST_SENT
, 0 },
257 { winhttp_receive_response
, WINHTTP_CALLBACK_STATUS_RECEIVING_RESPONSE
, 0 },
258 { winhttp_receive_response
, WINHTTP_CALLBACK_STATUS_RESPONSE_RECEIVED
, 0 },
259 { winhttp_close_handle
, WINHTTP_CALLBACK_STATUS_CLOSING_CONNECTION
, 0, 1 },
260 { winhttp_close_handle
, WINHTTP_CALLBACK_STATUS_CONNECTION_CLOSED
, 0, 1 },
261 { winhttp_close_handle
, WINHTTP_CALLBACK_STATUS_HANDLE_CLOSING
, 0, 1 },
262 { winhttp_close_handle
, WINHTTP_CALLBACK_STATUS_HANDLE_CLOSING
, 1, 1 },
263 { winhttp_close_handle
, WINHTTP_CALLBACK_STATUS_HANDLE_CLOSING
, 1, 1 }
266 static void test_redirect( void )
268 static const WCHAR codeweavers
[] = {'c','o','d','e','w','e','a','v','e','r','s','.','c','o','m',0};
270 HANDLE ses
, con
, req
;
273 struct info info
, *context
= &info
;
275 info
.test
= redirect_test
;
276 info
.count
= sizeof(redirect_test
) / sizeof(redirect_test
[0]);
280 ses
= WinHttpOpen( user_agent
, 0, NULL
, NULL
, 0 );
281 ok(ses
!= NULL
, "failed to open session %u\n", GetLastError());
283 WinHttpSetStatusCallback( ses
, check_notification
, WINHTTP_CALLBACK_FLAG_ALL_NOTIFICATIONS
, 0 );
285 ret
= WinHttpSetOption( ses
, WINHTTP_OPTION_CONTEXT_VALUE
, &context
, sizeof(struct info
*) );
286 ok(ret
, "failed to set context value %u\n", GetLastError());
288 setup_test( &info
, winhttp_connect
, __LINE__
);
289 con
= WinHttpConnect( ses
, codeweavers
, 0, 0 );
290 ok(con
!= NULL
, "failed to open a connection %u\n", GetLastError());
292 setup_test( &info
, winhttp_open_request
, __LINE__
);
293 req
= WinHttpOpenRequest( con
, NULL
, NULL
, NULL
, NULL
, NULL
, 0 );
294 ok(req
!= NULL
, "failed to open a request %u\n", GetLastError());
296 setup_test( &info
, winhttp_send_request
, __LINE__
);
297 ret
= WinHttpSendRequest( req
, NULL
, 0, NULL
, 0, 0, 0 );
298 ok(ret
, "failed to send request %u\n", GetLastError());
300 setup_test( &info
, winhttp_receive_response
, __LINE__
);
301 ret
= WinHttpReceiveResponse( req
, NULL
);
302 ok(ret
, "failed to receive response %u\n", GetLastError());
304 size
= sizeof(status
);
305 ret
= WinHttpQueryHeaders( req
, WINHTTP_QUERY_STATUS_CODE
| WINHTTP_QUERY_FLAG_NUMBER
, NULL
, &status
, &size
, NULL
);
306 ok(ret
, "failed unexpectedly %u\n", GetLastError());
307 ok(status
== 200, "request failed unexpectedly %u\n", status
);
309 setup_test( &info
, winhttp_close_handle
, __LINE__
);
310 WinHttpCloseHandle( req
);
311 WinHttpCloseHandle( con
);
312 WinHttpCloseHandle( ses
);
315 static const struct notification async_test
[] =
317 { winhttp_connect
, WINHTTP_CALLBACK_STATUS_HANDLE_CREATED
, 0 },
318 { winhttp_open_request
, WINHTTP_CALLBACK_STATUS_HANDLE_CREATED
, 0 },
319 { winhttp_send_request
, WINHTTP_CALLBACK_STATUS_RESOLVING_NAME
, 0 },
320 { winhttp_send_request
, WINHTTP_CALLBACK_STATUS_NAME_RESOLVED
, 0 },
321 { winhttp_send_request
, WINHTTP_CALLBACK_STATUS_CONNECTING_TO_SERVER
, 0 },
322 { winhttp_send_request
, WINHTTP_CALLBACK_STATUS_CONNECTED_TO_SERVER
, 0 },
323 { winhttp_send_request
, WINHTTP_CALLBACK_STATUS_SENDING_REQUEST
, 0 },
324 { winhttp_send_request
, WINHTTP_CALLBACK_STATUS_REQUEST_SENT
, 0 },
325 { winhttp_send_request
, WINHTTP_CALLBACK_STATUS_SENDREQUEST_COMPLETE
, 0 },
326 { winhttp_receive_response
, WINHTTP_CALLBACK_STATUS_RECEIVING_RESPONSE
, 0 },
327 { winhttp_receive_response
, WINHTTP_CALLBACK_STATUS_RESPONSE_RECEIVED
, 0 },
328 { winhttp_receive_response
, WINHTTP_CALLBACK_STATUS_REDIRECT
, 0 },
329 { winhttp_receive_response
, WINHTTP_CALLBACK_STATUS_RESOLVING_NAME
, 0, 0, 1 },
330 { winhttp_receive_response
, WINHTTP_CALLBACK_STATUS_NAME_RESOLVED
, 0, 0, 1 },
331 { winhttp_receive_response
, WINHTTP_CALLBACK_STATUS_CONNECTING_TO_SERVER
, 0, 0, 1 },
332 { winhttp_receive_response
, WINHTTP_CALLBACK_STATUS_CONNECTED_TO_SERVER
, 0, 0, 1 },
333 { winhttp_receive_response
, WINHTTP_CALLBACK_STATUS_SENDING_REQUEST
, 0 },
334 { winhttp_receive_response
, WINHTTP_CALLBACK_STATUS_REQUEST_SENT
, 0 },
335 { winhttp_receive_response
, WINHTTP_CALLBACK_STATUS_RECEIVING_RESPONSE
, 0 },
336 { winhttp_receive_response
, WINHTTP_CALLBACK_STATUS_RESPONSE_RECEIVED
, 0 },
337 { winhttp_receive_response
, WINHTTP_CALLBACK_STATUS_HEADERS_AVAILABLE
, 0 },
338 { winhttp_query_data
, WINHTTP_CALLBACK_STATUS_DATA_AVAILABLE
, 0 },
339 { winhttp_read_data
, WINHTTP_CALLBACK_STATUS_RECEIVING_RESPONSE
, 0, 1 },
340 { winhttp_read_data
, WINHTTP_CALLBACK_STATUS_RESPONSE_RECEIVED
, 0, 1 },
341 { winhttp_read_data
, WINHTTP_CALLBACK_STATUS_READ_COMPLETE
, 0, 1 },
342 { winhttp_close_handle
, WINHTTP_CALLBACK_STATUS_CLOSING_CONNECTION
, 0, 1 },
343 { winhttp_close_handle
, WINHTTP_CALLBACK_STATUS_CONNECTION_CLOSED
, 0, 1 },
344 { winhttp_close_handle
, WINHTTP_CALLBACK_STATUS_HANDLE_CLOSING
, 0, 1 },
345 { winhttp_close_handle
, WINHTTP_CALLBACK_STATUS_HANDLE_CLOSING
, 1, 1 },
346 { winhttp_close_handle
, WINHTTP_CALLBACK_STATUS_HANDLE_CLOSING
, 1, 1 }
349 static void test_async( void )
351 static const WCHAR codeweavers
[] = {'c','o','d','e','w','e','a','v','e','r','s','.','c','o','m',0};
353 HANDLE ses
, con
, req
;
356 struct info info
, *context
= &info
;
359 info
.test
= async_test
;
360 info
.count
= sizeof(async_test
) / sizeof(async_test
[0]);
362 info
.wait
= CreateEvent( NULL
, FALSE
, FALSE
, NULL
);
364 ses
= WinHttpOpen( user_agent
, 0, NULL
, NULL
, WINHTTP_FLAG_ASYNC
);
365 ok(ses
!= NULL
, "failed to open session %u\n", GetLastError());
367 WinHttpSetStatusCallback( ses
, check_notification
, WINHTTP_CALLBACK_FLAG_ALL_NOTIFICATIONS
, 0 );
369 ret
= WinHttpSetOption( ses
, WINHTTP_OPTION_CONTEXT_VALUE
, &context
, sizeof(struct info
*) );
370 ok(ret
, "failed to set context value %u\n", GetLastError());
372 setup_test( &info
, winhttp_connect
, __LINE__
);
373 con
= WinHttpConnect( ses
, codeweavers
, 0, 0 );
374 ok(con
!= NULL
, "failed to open a connection %u\n", GetLastError());
376 setup_test( &info
, winhttp_open_request
, __LINE__
);
377 req
= WinHttpOpenRequest( con
, NULL
, NULL
, NULL
, NULL
, NULL
, 0 );
378 ok(req
!= NULL
, "failed to open a request %u\n", GetLastError());
380 setup_test( &info
, winhttp_send_request
, __LINE__
);
381 ret
= WinHttpSendRequest( req
, NULL
, 0, NULL
, 0, 0, 0 );
382 ok(ret
, "failed to send request %u\n", GetLastError());
384 WaitForSingleObject( info
.wait
, INFINITE
);
386 setup_test( &info
, winhttp_receive_response
, __LINE__
);
387 ret
= WinHttpReceiveResponse( req
, NULL
);
388 ok(ret
, "failed to receive response %u\n", GetLastError());
390 WaitForSingleObject( info
.wait
, INFINITE
);
392 size
= sizeof(status
);
393 ret
= WinHttpQueryHeaders( req
, WINHTTP_QUERY_STATUS_CODE
| WINHTTP_QUERY_FLAG_NUMBER
, NULL
, &status
, &size
, NULL
);
394 ok(ret
, "failed unexpectedly %u\n", GetLastError());
395 ok(status
== 200, "request failed unexpectedly %u\n", status
);
397 setup_test( &info
, winhttp_query_data
, __LINE__
);
398 ret
= WinHttpQueryDataAvailable( req
, NULL
);
399 ok(ret
, "failed to query data available %u\n", GetLastError());
401 WaitForSingleObject( info
.wait
, INFINITE
);
403 setup_test( &info
, winhttp_read_data
, __LINE__
);
404 ret
= WinHttpReadData( req
, buffer
, sizeof(buffer
), NULL
);
405 ok(ret
, "failed to query data available %u\n", GetLastError());
407 WaitForSingleObject( info
.wait
, INFINITE
);
409 setup_test( &info
, winhttp_close_handle
, __LINE__
);
410 WinHttpCloseHandle( req
);
411 WinHttpCloseHandle( con
);
412 WinHttpCloseHandle( ses
);
414 WaitForSingleObject( info
.wait
, INFINITE
);
415 CloseHandle( info
.wait
);
418 START_TEST (notification
)
420 test_connection_cache();
422 Sleep(2000); /* make sure previous connection is evicted from cache */