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 */
54 const struct notification
*test
;
61 static void CALLBACK
check_notification( HINTERNET handle
, DWORD_PTR context
, DWORD status
, LPVOID buffer
, DWORD buflen
)
63 BOOL status_ok
, function_ok
;
64 struct info
*info
= (struct info
*)context
;
65 unsigned int i
= info
->index
;
67 if (status
== WINHTTP_CALLBACK_STATUS_HANDLE_CREATED
)
69 DWORD size
= sizeof(struct info
*);
70 WinHttpQueryOption( handle
, WINHTTP_OPTION_CONTEXT_VALUE
, &info
, &size
);
72 ok(i
< info
->count
, "unexpected notification 0x%08x\n", status
);
73 if (i
>= info
->count
) return;
75 status_ok
= (info
->test
[i
].status
== status
);
76 function_ok
= (info
->test
[i
].function
== info
->function
);
77 if (!info
->test
[i
].ignore
&& !info
->test
[i
].todo
)
79 ok(status_ok
, "%u: expected status 0x%08x got 0x%08x\n", info
->line
, info
->test
[i
].status
, status
);
80 ok(function_ok
, "%u: expected function %u got %u\n", info
->line
, info
->test
[i
].function
, info
->function
);
82 else if (!info
->test
[i
].ignore
)
84 todo_wine
ok(status_ok
, "%u: expected status 0x%08x got 0x%08x\n", info
->line
, info
->test
[i
].status
, status
);
87 todo_wine
ok(function_ok
, "%u: expected function %u got %u\n", info
->line
, info
->test
[i
].function
, info
->function
);
90 if (status_ok
) info
->index
++;
91 if (status
& (WINHTTP_CALLBACK_FLAG_ALL_COMPLETIONS
| WINHTTP_CALLBACK_STATUS_HANDLE_CLOSING
))
93 SetEvent( info
->wait
);
97 static const struct notification cache_test
[] =
99 { winhttp_connect
, WINHTTP_CALLBACK_STATUS_HANDLE_CREATED
, 0 },
100 { winhttp_open_request
, WINHTTP_CALLBACK_STATUS_HANDLE_CREATED
, 0 },
101 { winhttp_send_request
, WINHTTP_CALLBACK_STATUS_RESOLVING_NAME
, 0 },
102 { winhttp_send_request
, WINHTTP_CALLBACK_STATUS_NAME_RESOLVED
, 0 },
103 { winhttp_send_request
, WINHTTP_CALLBACK_STATUS_CONNECTING_TO_SERVER
, 0 },
104 { winhttp_send_request
, WINHTTP_CALLBACK_STATUS_CONNECTED_TO_SERVER
, 0 },
105 { winhttp_send_request
, WINHTTP_CALLBACK_STATUS_SENDING_REQUEST
, 0 },
106 { winhttp_send_request
, WINHTTP_CALLBACK_STATUS_REQUEST_SENT
, 0 },
107 { winhttp_receive_response
, WINHTTP_CALLBACK_STATUS_RECEIVING_RESPONSE
, 0 },
108 { winhttp_receive_response
, WINHTTP_CALLBACK_STATUS_RESPONSE_RECEIVED
, 0 },
109 { winhttp_close_handle
, WINHTTP_CALLBACK_STATUS_CLOSING_CONNECTION
, 0, 1 },
110 { winhttp_close_handle
, WINHTTP_CALLBACK_STATUS_CONNECTION_CLOSED
, 0, 1 },
111 { winhttp_close_handle
, WINHTTP_CALLBACK_STATUS_HANDLE_CLOSING
, 0, 1 },
112 { winhttp_close_handle
, WINHTTP_CALLBACK_STATUS_HANDLE_CLOSING
, 1, 1 },
113 { winhttp_close_handle
, WINHTTP_CALLBACK_STATUS_HANDLE_CLOSING
, 1, 1 }
116 static void setup_test( struct info
*info
, enum api function
, unsigned int line
)
118 info
->function
= function
;
122 static void test_connection_cache( void )
124 static const WCHAR codeweavers
[] = {'w','w','w','.','c','o','d','e','w','e','a','v','e','r','s','.','c','o','m',0};
126 HANDLE ses
, con
, req
;
129 struct info info
, *context
= &info
;
131 info
.test
= cache_test
;
132 info
.count
= sizeof(cache_test
) / sizeof(cache_test
[0]);
136 ses
= WinHttpOpen( user_agent
, 0, NULL
, NULL
, 0 );
137 ok(ses
!= NULL
, "failed to open session %u\n", GetLastError());
139 WinHttpSetStatusCallback( ses
, check_notification
, WINHTTP_CALLBACK_FLAG_ALL_NOTIFICATIONS
, 0 );
141 ret
= WinHttpSetOption( ses
, WINHTTP_OPTION_CONTEXT_VALUE
, &context
, sizeof(struct info
*) );
142 ok(ret
, "failed to set context value %u\n", GetLastError());
144 setup_test( &info
, winhttp_connect
, __LINE__
);
145 con
= WinHttpConnect( ses
, codeweavers
, 0, 0 );
146 ok(con
!= NULL
, "failed to open a connection %u\n", GetLastError());
148 setup_test( &info
, winhttp_open_request
, __LINE__
);
149 req
= WinHttpOpenRequest( con
, NULL
, NULL
, NULL
, NULL
, NULL
, 0 );
150 ok(req
!= NULL
, "failed to open a request %u\n", GetLastError());
152 setup_test( &info
, winhttp_send_request
, __LINE__
);
153 ret
= WinHttpSendRequest( req
, NULL
, 0, NULL
, 0, 0, 0 );
154 ok(ret
, "failed to send request %u\n", GetLastError());
156 setup_test( &info
, winhttp_receive_response
, __LINE__
);
157 ret
= WinHttpReceiveResponse( req
, NULL
);
158 ok(ret
, "failed to receive response %u\n", GetLastError());
160 size
= sizeof(status
);
161 ret
= WinHttpQueryHeaders( req
, WINHTTP_QUERY_STATUS_CODE
| WINHTTP_QUERY_FLAG_NUMBER
, NULL
, &status
, &size
, NULL
);
162 ok(ret
, "failed unexpectedly %u\n", GetLastError());
163 ok(status
== 200, "request failed unexpectedly %u\n", status
);
165 setup_test( &info
, winhttp_close_handle
, __LINE__
);
166 WinHttpCloseHandle( req
);
167 WinHttpCloseHandle( con
);
168 WinHttpCloseHandle( ses
);
170 Sleep(2000); /* make sure connection is evicted from cache */
174 ses
= WinHttpOpen( user_agent
, 0, NULL
, NULL
, 0 );
175 ok(ses
!= NULL
, "failed to open session %u\n", GetLastError());
177 WinHttpSetStatusCallback( ses
, check_notification
, WINHTTP_CALLBACK_FLAG_ALL_NOTIFICATIONS
, 0 );
179 ret
= WinHttpSetOption( ses
, WINHTTP_OPTION_CONTEXT_VALUE
, &context
, sizeof(struct info
*) );
180 ok(ret
, "failed to set context value %u\n", GetLastError());
182 setup_test( &info
, winhttp_connect
, __LINE__
);
183 con
= WinHttpConnect( ses
, codeweavers
, 0, 0 );
184 ok(con
!= NULL
, "failed to open a connection %u\n", GetLastError());
186 setup_test( &info
, winhttp_open_request
, __LINE__
);
187 req
= WinHttpOpenRequest( con
, NULL
, NULL
, NULL
, NULL
, NULL
, 0 );
188 ok(req
!= NULL
, "failed to open a request %u\n", GetLastError());
190 ret
= WinHttpSetOption( req
, WINHTTP_OPTION_CONTEXT_VALUE
, &context
, sizeof(struct info
*) );
191 ok(ret
, "failed to set context value %u\n", GetLastError());
193 setup_test( &info
, winhttp_send_request
, __LINE__
);
194 ret
= WinHttpSendRequest( req
, NULL
, 0, NULL
, 0, 0, 0 );
195 ok(ret
, "failed to send request %u\n", GetLastError());
197 setup_test( &info
, winhttp_receive_response
, __LINE__
);
198 ret
= WinHttpReceiveResponse( req
, NULL
);
199 ok(ret
, "failed to receive response %u\n", GetLastError());
201 size
= sizeof(status
);
202 ret
= WinHttpQueryHeaders( req
, WINHTTP_QUERY_STATUS_CODE
| WINHTTP_QUERY_FLAG_NUMBER
, NULL
, &status
, &size
, NULL
);
203 ok(ret
, "failed unexpectedly %u\n", GetLastError());
204 ok(status
== 200, "request failed unexpectedly %u\n", status
);
206 setup_test( &info
, winhttp_close_handle
, __LINE__
);
207 WinHttpCloseHandle( req
);
208 WinHttpCloseHandle( con
);
209 WinHttpCloseHandle( ses
);
212 static const struct notification redirect_test
[] =
214 { winhttp_connect
, WINHTTP_CALLBACK_STATUS_HANDLE_CREATED
, 0 },
215 { winhttp_open_request
, WINHTTP_CALLBACK_STATUS_HANDLE_CREATED
, 0 },
216 { winhttp_send_request
, WINHTTP_CALLBACK_STATUS_RESOLVING_NAME
, 0 },
217 { winhttp_send_request
, WINHTTP_CALLBACK_STATUS_NAME_RESOLVED
, 0 },
218 { winhttp_send_request
, WINHTTP_CALLBACK_STATUS_CONNECTING_TO_SERVER
, 0 },
219 { winhttp_send_request
, WINHTTP_CALLBACK_STATUS_CONNECTED_TO_SERVER
, 0 },
220 { winhttp_send_request
, WINHTTP_CALLBACK_STATUS_SENDING_REQUEST
, 0 },
221 { winhttp_send_request
, WINHTTP_CALLBACK_STATUS_REQUEST_SENT
, 0 },
222 { winhttp_receive_response
, WINHTTP_CALLBACK_STATUS_RECEIVING_RESPONSE
, 0 },
223 { winhttp_receive_response
, WINHTTP_CALLBACK_STATUS_RESPONSE_RECEIVED
, 0 },
224 { winhttp_receive_response
, WINHTTP_CALLBACK_STATUS_REDIRECT
, 0 },
225 { winhttp_receive_response
, WINHTTP_CALLBACK_STATUS_RESOLVING_NAME
, 0 },
226 { winhttp_receive_response
, WINHTTP_CALLBACK_STATUS_NAME_RESOLVED
, 0 },
227 { winhttp_receive_response
, WINHTTP_CALLBACK_STATUS_CONNECTING_TO_SERVER
, 0 },
228 { winhttp_receive_response
, WINHTTP_CALLBACK_STATUS_CONNECTED_TO_SERVER
, 0 },
229 { winhttp_receive_response
, WINHTTP_CALLBACK_STATUS_SENDING_REQUEST
, 0 },
230 { winhttp_receive_response
, WINHTTP_CALLBACK_STATUS_REQUEST_SENT
, 0 },
231 { winhttp_receive_response
, WINHTTP_CALLBACK_STATUS_RECEIVING_RESPONSE
, 0 },
232 { winhttp_receive_response
, WINHTTP_CALLBACK_STATUS_RESPONSE_RECEIVED
, 0 },
233 { winhttp_close_handle
, WINHTTP_CALLBACK_STATUS_CLOSING_CONNECTION
, 0, 1 },
234 { winhttp_close_handle
, WINHTTP_CALLBACK_STATUS_CONNECTION_CLOSED
, 0, 1 },
235 { winhttp_close_handle
, WINHTTP_CALLBACK_STATUS_HANDLE_CLOSING
, 0, 1 },
236 { winhttp_close_handle
, WINHTTP_CALLBACK_STATUS_HANDLE_CLOSING
, 1, 1 },
237 { winhttp_close_handle
, WINHTTP_CALLBACK_STATUS_HANDLE_CLOSING
, 1, 1 }
240 static void test_redirect( void )
242 static const WCHAR codeweavers
[] = {'c','o','d','e','w','e','a','v','e','r','s','.','c','o','m',0};
244 HANDLE ses
, con
, req
;
247 struct info info
, *context
= &info
;
249 info
.test
= redirect_test
;
250 info
.count
= sizeof(redirect_test
) / sizeof(redirect_test
[0]);
254 ses
= WinHttpOpen( user_agent
, 0, NULL
, NULL
, 0 );
255 ok(ses
!= NULL
, "failed to open session %u\n", GetLastError());
257 WinHttpSetStatusCallback( ses
, check_notification
, WINHTTP_CALLBACK_FLAG_ALL_NOTIFICATIONS
, 0 );
259 ret
= WinHttpSetOption( ses
, WINHTTP_OPTION_CONTEXT_VALUE
, &context
, sizeof(struct info
*) );
260 ok(ret
, "failed to set context value %u\n", GetLastError());
262 setup_test( &info
, winhttp_connect
, __LINE__
);
263 con
= WinHttpConnect( ses
, codeweavers
, 0, 0 );
264 ok(con
!= NULL
, "failed to open a connection %u\n", GetLastError());
266 setup_test( &info
, winhttp_open_request
, __LINE__
);
267 req
= WinHttpOpenRequest( con
, NULL
, NULL
, NULL
, NULL
, NULL
, 0 );
268 ok(req
!= NULL
, "failed to open a request %u\n", GetLastError());
270 setup_test( &info
, winhttp_send_request
, __LINE__
);
271 ret
= WinHttpSendRequest( req
, NULL
, 0, NULL
, 0, 0, 0 );
273 setup_test( &info
, winhttp_receive_response
, __LINE__
);
274 ret
= WinHttpReceiveResponse( req
, NULL
);
275 ok(ret
, "failed to receive response %u\n", GetLastError());
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
);
282 setup_test( &info
, winhttp_close_handle
, __LINE__
);
283 WinHttpCloseHandle( req
);
284 WinHttpCloseHandle( con
);
285 WinHttpCloseHandle( ses
);
288 static const struct notification async_test
[] =
290 { winhttp_connect
, WINHTTP_CALLBACK_STATUS_HANDLE_CREATED
, 0 },
291 { winhttp_open_request
, WINHTTP_CALLBACK_STATUS_HANDLE_CREATED
, 0 },
292 { winhttp_send_request
, WINHTTP_CALLBACK_STATUS_RESOLVING_NAME
, 0 },
293 { winhttp_send_request
, WINHTTP_CALLBACK_STATUS_NAME_RESOLVED
, 0 },
294 { winhttp_send_request
, WINHTTP_CALLBACK_STATUS_CONNECTING_TO_SERVER
, 0 },
295 { winhttp_send_request
, WINHTTP_CALLBACK_STATUS_CONNECTED_TO_SERVER
, 0 },
296 { winhttp_send_request
, WINHTTP_CALLBACK_STATUS_SENDING_REQUEST
, 0 },
297 { winhttp_send_request
, WINHTTP_CALLBACK_STATUS_REQUEST_SENT
, 0 },
298 { winhttp_send_request
, WINHTTP_CALLBACK_STATUS_SENDREQUEST_COMPLETE
, 0 },
299 { winhttp_receive_response
, WINHTTP_CALLBACK_STATUS_RECEIVING_RESPONSE
, 0 },
300 { winhttp_receive_response
, WINHTTP_CALLBACK_STATUS_RESPONSE_RECEIVED
, 0 },
301 { winhttp_receive_response
, WINHTTP_CALLBACK_STATUS_REDIRECT
, 0 },
302 { winhttp_receive_response
, WINHTTP_CALLBACK_STATUS_RESOLVING_NAME
, 0 },
303 { winhttp_receive_response
, WINHTTP_CALLBACK_STATUS_NAME_RESOLVED
, 0 },
304 { winhttp_receive_response
, WINHTTP_CALLBACK_STATUS_CONNECTING_TO_SERVER
, 0 },
305 { winhttp_receive_response
, WINHTTP_CALLBACK_STATUS_CONNECTED_TO_SERVER
, 0 },
306 { winhttp_receive_response
, WINHTTP_CALLBACK_STATUS_SENDING_REQUEST
, 0 },
307 { winhttp_receive_response
, WINHTTP_CALLBACK_STATUS_REQUEST_SENT
, 0 },
308 { winhttp_receive_response
, WINHTTP_CALLBACK_STATUS_RECEIVING_RESPONSE
, 0 },
309 { winhttp_receive_response
, WINHTTP_CALLBACK_STATUS_RESPONSE_RECEIVED
, 0 },
310 { winhttp_receive_response
, WINHTTP_CALLBACK_STATUS_HEADERS_AVAILABLE
, 0 },
311 { winhttp_query_data
, WINHTTP_CALLBACK_STATUS_DATA_AVAILABLE
, 0 },
312 { winhttp_read_data
, WINHTTP_CALLBACK_STATUS_RECEIVING_RESPONSE
, 0, 1 },
313 { winhttp_read_data
, WINHTTP_CALLBACK_STATUS_RESPONSE_RECEIVED
, 0, 1 },
314 { winhttp_read_data
, WINHTTP_CALLBACK_STATUS_READ_COMPLETE
, 0, 1 },
315 { winhttp_close_handle
, WINHTTP_CALLBACK_STATUS_CLOSING_CONNECTION
, 0, 1 },
316 { winhttp_close_handle
, WINHTTP_CALLBACK_STATUS_CONNECTION_CLOSED
, 0, 1 },
317 { winhttp_close_handle
, WINHTTP_CALLBACK_STATUS_HANDLE_CLOSING
, 0, 1 },
318 { winhttp_close_handle
, WINHTTP_CALLBACK_STATUS_HANDLE_CLOSING
, 1, 1 },
319 { winhttp_close_handle
, WINHTTP_CALLBACK_STATUS_HANDLE_CLOSING
, 1, 1 }
322 static void test_async( void )
324 static const WCHAR codeweavers
[] = {'c','o','d','e','w','e','a','v','e','r','s','.','c','o','m',0};
326 HANDLE ses
, con
, req
;
329 struct info info
, *context
= &info
;
332 info
.test
= async_test
;
333 info
.count
= sizeof(async_test
) / sizeof(async_test
[0]);
335 info
.wait
= CreateEvent( NULL
, FALSE
, FALSE
, NULL
);
337 ses
= WinHttpOpen( user_agent
, 0, NULL
, NULL
, WINHTTP_FLAG_ASYNC
);
338 ok(ses
!= NULL
, "failed to open session %u\n", GetLastError());
340 WinHttpSetStatusCallback( ses
, check_notification
, WINHTTP_CALLBACK_FLAG_ALL_NOTIFICATIONS
, 0 );
342 ret
= WinHttpSetOption( ses
, WINHTTP_OPTION_CONTEXT_VALUE
, &context
, sizeof(struct info
*) );
343 ok(ret
, "failed to set context value %u\n", GetLastError());
345 setup_test( &info
, winhttp_connect
, __LINE__
);
346 con
= WinHttpConnect( ses
, codeweavers
, 0, 0 );
347 ok(con
!= NULL
, "failed to open a connection %u\n", GetLastError());
349 setup_test( &info
, winhttp_open_request
, __LINE__
);
350 req
= WinHttpOpenRequest( con
, NULL
, NULL
, NULL
, NULL
, NULL
, 0 );
351 ok(req
!= NULL
, "failed to open a request %u\n", GetLastError());
353 setup_test( &info
, winhttp_send_request
, __LINE__
);
354 ret
= WinHttpSendRequest( req
, NULL
, 0, NULL
, 0, 0, 0 );
355 ok(ret
, "failed to send request %u\n", GetLastError());
357 WaitForSingleObject( info
.wait
, INFINITE
);
359 setup_test( &info
, winhttp_receive_response
, __LINE__
);
360 ret
= WinHttpReceiveResponse( req
, NULL
);
361 ok(ret
, "failed to receive response %u\n", GetLastError());
363 WaitForSingleObject( info
.wait
, INFINITE
);
365 size
= sizeof(status
);
366 ret
= WinHttpQueryHeaders( req
, WINHTTP_QUERY_STATUS_CODE
| WINHTTP_QUERY_FLAG_NUMBER
, NULL
, &status
, &size
, NULL
);
367 ok(ret
, "failed unexpectedly %u\n", GetLastError());
368 ok(status
== 200, "request failed unexpectedly %u\n", status
);
370 setup_test( &info
, winhttp_query_data
, __LINE__
);
371 ret
= WinHttpQueryDataAvailable( req
, NULL
);
372 ok(ret
, "failed to query data available %u\n", GetLastError());
374 WaitForSingleObject( info
.wait
, INFINITE
);
376 setup_test( &info
, winhttp_read_data
, __LINE__
);
377 ret
= WinHttpReadData( req
, buffer
, sizeof(buffer
), NULL
);
378 ok(ret
, "failed to query data available %u\n", GetLastError());
380 WaitForSingleObject( info
.wait
, INFINITE
);
382 setup_test( &info
, winhttp_close_handle
, __LINE__
);
383 WinHttpCloseHandle( req
);
384 WinHttpCloseHandle( con
);
385 WinHttpCloseHandle( ses
);
387 WaitForSingleObject( info
.wait
, INFINITE
);
388 CloseHandle( info
.wait
);
391 START_TEST (notification
)
393 test_connection_cache();
395 Sleep(2000); /* make sure previous connection is evicted from cache */