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
29 #include "wine/test.h"
31 static const WCHAR user_agent
[] = {'w','i','n','e','t','e','s','t',0};
32 static const WCHAR test_winehq
[] = {'t','e','s','t','.','w','i','n','e','h','q','.','o','r','g',0};
33 static const WCHAR tests_hello_html
[] = {'/','t','e','s','t','s','/','h','e','l','l','o','.','h','t','m','l',0};
34 static const WCHAR tests_redirect
[] = {'/','t','e','s','t','s','/','r','e','d','i','r','e','c','t',0};
35 static const WCHAR localhostW
[] = {'l','o','c','a','l','h','o','s','t',0};
42 winhttp_receive_response
,
51 enum api function
; /* api responsible for notification */
52 unsigned int status
; /* status received */
53 DWORD flags
; /* a combination of NF_* flags */
56 #define NF_ALLOW 0x0001 /* notification may or may not happen */
57 #define NF_WINE_ALLOW 0x0002 /* wine sends notification when it should not */
58 #define NF_SIGNAL 0x0004 /* signal wait handle when notified */
63 const struct notification
*test
;
77 static void CALLBACK
check_notification( HINTERNET handle
, DWORD_PTR context
, DWORD status
, LPVOID buffer
, DWORD buflen
)
79 BOOL status_ok
, function_ok
;
80 struct info
*info
= (struct info
*)context
;
82 if (status
== WINHTTP_CALLBACK_STATUS_HANDLE_CREATED
)
84 DWORD size
= sizeof(struct info
*);
85 WinHttpQueryOption( handle
, WINHTTP_OPTION_CONTEXT_VALUE
, &info
, &size
);
87 while (info
->index
< info
->count
&& info
->test
[info
->index
].status
!= status
&& (info
->test
[info
->index
].flags
& NF_ALLOW
))
89 while (info
->index
< info
->count
&& (info
->test
[info
->index
].flags
& NF_WINE_ALLOW
))
91 todo_wine
ok(info
->test
[info
->index
].status
!= status
, "unexpected %x notification\n", status
);
92 if (info
->test
[info
->index
].status
== status
) break;
95 ok(info
->index
< info
->count
, "%u: unexpected notification 0x%08x\n", info
->line
, status
);
96 if (info
->index
>= info
->count
) return;
98 status_ok
= (info
->test
[info
->index
].status
== status
);
99 function_ok
= (info
->test
[info
->index
].function
== info
->function
);
100 ok(status_ok
, "%u: expected status 0x%08x got 0x%08x\n", info
->line
, info
->test
[info
->index
].status
, status
);
101 ok(function_ok
, "%u: expected function %u got %u\n", info
->line
, info
->test
[info
->index
].function
, info
->function
);
103 if (status_ok
&& function_ok
&& info
->test
[info
->index
++].flags
& NF_SIGNAL
)
105 SetEvent( info
->wait
);
109 static const struct notification cache_test
[] =
111 { winhttp_connect
, WINHTTP_CALLBACK_STATUS_HANDLE_CREATED
},
112 { winhttp_open_request
, WINHTTP_CALLBACK_STATUS_HANDLE_CREATED
},
113 { winhttp_send_request
, WINHTTP_CALLBACK_STATUS_RESOLVING_NAME
},
114 { winhttp_send_request
, WINHTTP_CALLBACK_STATUS_NAME_RESOLVED
},
115 { winhttp_send_request
, WINHTTP_CALLBACK_STATUS_CONNECTING_TO_SERVER
},
116 { winhttp_send_request
, WINHTTP_CALLBACK_STATUS_CONNECTED_TO_SERVER
},
117 { winhttp_send_request
, WINHTTP_CALLBACK_STATUS_SENDING_REQUEST
},
118 { winhttp_send_request
, WINHTTP_CALLBACK_STATUS_REQUEST_SENT
},
119 { winhttp_receive_response
, WINHTTP_CALLBACK_STATUS_RECEIVING_RESPONSE
},
120 { winhttp_receive_response
, WINHTTP_CALLBACK_STATUS_RESPONSE_RECEIVED
},
121 { winhttp_close_handle
, WINHTTP_CALLBACK_STATUS_CLOSING_CONNECTION
, NF_WINE_ALLOW
},
122 { winhttp_close_handle
, WINHTTP_CALLBACK_STATUS_CONNECTION_CLOSED
, NF_WINE_ALLOW
},
123 { winhttp_close_handle
, WINHTTP_CALLBACK_STATUS_HANDLE_CLOSING
, NF_SIGNAL
},
124 { winhttp_open_request
, WINHTTP_CALLBACK_STATUS_HANDLE_CREATED
},
125 { winhttp_send_request
, WINHTTP_CALLBACK_STATUS_CONNECTING_TO_SERVER
, NF_WINE_ALLOW
},
126 { winhttp_send_request
, WINHTTP_CALLBACK_STATUS_CONNECTED_TO_SERVER
, NF_WINE_ALLOW
},
127 { winhttp_send_request
, WINHTTP_CALLBACK_STATUS_SENDING_REQUEST
},
128 { winhttp_send_request
, WINHTTP_CALLBACK_STATUS_REQUEST_SENT
},
129 { winhttp_receive_response
, WINHTTP_CALLBACK_STATUS_RECEIVING_RESPONSE
},
130 { winhttp_receive_response
, WINHTTP_CALLBACK_STATUS_RESPONSE_RECEIVED
},
131 { winhttp_close_handle
, WINHTTP_CALLBACK_STATUS_CLOSING_CONNECTION
, NF_WINE_ALLOW
},
132 { winhttp_close_handle
, WINHTTP_CALLBACK_STATUS_CONNECTION_CLOSED
, NF_WINE_ALLOW
},
133 { winhttp_close_handle
, WINHTTP_CALLBACK_STATUS_HANDLE_CLOSING
},
134 { winhttp_close_handle
, WINHTTP_CALLBACK_STATUS_HANDLE_CLOSING
, NF_SIGNAL
},
135 { winhttp_close_handle
, WINHTTP_CALLBACK_STATUS_HANDLE_CLOSING
, NF_SIGNAL
},
136 { winhttp_connect
, WINHTTP_CALLBACK_STATUS_HANDLE_CREATED
},
137 { winhttp_open_request
, WINHTTP_CALLBACK_STATUS_HANDLE_CREATED
},
138 { winhttp_send_request
, WINHTTP_CALLBACK_STATUS_RESOLVING_NAME
, NF_WINE_ALLOW
},
139 { winhttp_send_request
, WINHTTP_CALLBACK_STATUS_NAME_RESOLVED
, NF_WINE_ALLOW
},
140 { winhttp_send_request
, WINHTTP_CALLBACK_STATUS_CONNECTING_TO_SERVER
, NF_WINE_ALLOW
},
141 { winhttp_send_request
, WINHTTP_CALLBACK_STATUS_CONNECTED_TO_SERVER
, NF_WINE_ALLOW
},
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
, NF_WINE_ALLOW
},
147 { winhttp_close_handle
, WINHTTP_CALLBACK_STATUS_CONNECTION_CLOSED
, NF_WINE_ALLOW
},
148 { winhttp_close_handle
, WINHTTP_CALLBACK_STATUS_HANDLE_CLOSING
, NF_SIGNAL
},
149 { winhttp_open_request
, WINHTTP_CALLBACK_STATUS_HANDLE_CREATED
},
150 { winhttp_send_request
, WINHTTP_CALLBACK_STATUS_CONNECTING_TO_SERVER
, NF_WINE_ALLOW
},
151 { winhttp_send_request
, WINHTTP_CALLBACK_STATUS_CONNECTED_TO_SERVER
, NF_WINE_ALLOW
},
152 { winhttp_send_request
, WINHTTP_CALLBACK_STATUS_SENDING_REQUEST
},
153 { winhttp_send_request
, WINHTTP_CALLBACK_STATUS_REQUEST_SENT
},
154 { winhttp_receive_response
, WINHTTP_CALLBACK_STATUS_RECEIVING_RESPONSE
},
155 { winhttp_receive_response
, WINHTTP_CALLBACK_STATUS_RESPONSE_RECEIVED
},
156 { winhttp_close_handle
, WINHTTP_CALLBACK_STATUS_CLOSING_CONNECTION
, NF_WINE_ALLOW
},
157 { winhttp_close_handle
, WINHTTP_CALLBACK_STATUS_CONNECTION_CLOSED
, NF_WINE_ALLOW
},
158 { winhttp_close_handle
, WINHTTP_CALLBACK_STATUS_HANDLE_CLOSING
},
159 { winhttp_close_handle
, WINHTTP_CALLBACK_STATUS_HANDLE_CLOSING
, NF_SIGNAL
},
160 { winhttp_close_handle
, WINHTTP_CALLBACK_STATUS_HANDLE_CLOSING
, NF_SIGNAL
}
163 static void setup_test( struct info
*info
, enum api function
, unsigned int line
)
165 if (info
->wait
) ResetEvent( info
->wait
);
166 info
->function
= function
;
168 while (info
->index
< info
->count
&& info
->test
[info
->index
].function
!= function
169 && (info
->test
[info
->index
].flags
& (NF_ALLOW
| NF_WINE_ALLOW
)))
171 ok_(__FILE__
,line
)(info
->test
[info
->index
].function
== function
,
172 "unexpected function %u, expected %u. probably some notifications were missing\n",
173 info
->test
[info
->index
].function
, function
);
176 static void end_test( struct info
*info
, unsigned int line
)
178 ok_(__FILE__
,line
)(info
->index
== info
->count
, "some notifications were missing: %x\n",
179 info
->test
[info
->index
].status
);
182 static void test_connection_cache( void )
184 HANDLE ses
, con
, req
, event
;
185 DWORD size
, status
, err
;
186 BOOL ret
, unload
= TRUE
;
187 struct info info
, *context
= &info
;
189 info
.test
= cache_test
;
190 info
.count
= sizeof(cache_test
) / sizeof(cache_test
[0]);
192 info
.wait
= CreateEventW( NULL
, FALSE
, FALSE
, NULL
);
194 ses
= WinHttpOpen( user_agent
, 0, NULL
, NULL
, 0 );
195 ok(ses
!= NULL
, "failed to open session %u\n", GetLastError());
197 event
= CreateEventW( NULL
, FALSE
, FALSE
, NULL
);
198 ret
= WinHttpSetOption( ses
, WINHTTP_OPTION_UNLOAD_NOTIFY_EVENT
, &event
, sizeof(event
) );
201 win_skip("Unload event not supported\n");
205 WinHttpSetStatusCallback( ses
, check_notification
, WINHTTP_CALLBACK_FLAG_ALL_NOTIFICATIONS
, 0 );
207 ret
= WinHttpSetOption( ses
, WINHTTP_OPTION_CONTEXT_VALUE
, &context
, sizeof(struct info
*) );
208 ok(ret
, "failed to set context value %u\n", GetLastError());
210 setup_test( &info
, winhttp_connect
, __LINE__
);
211 con
= WinHttpConnect( ses
, test_winehq
, 0, 0 );
212 ok(con
!= NULL
, "failed to open a connection %u\n", GetLastError());
214 setup_test( &info
, winhttp_open_request
, __LINE__
);
215 req
= WinHttpOpenRequest( con
, NULL
, tests_hello_html
, NULL
, NULL
, NULL
, 0 );
216 ok(req
!= NULL
, "failed to open a request %u\n", GetLastError());
218 setup_test( &info
, winhttp_send_request
, __LINE__
);
219 ret
= WinHttpSendRequest( req
, NULL
, 0, NULL
, 0, 0, 0 );
220 err
= GetLastError();
221 if (!ret
&& (err
== ERROR_WINHTTP_CANNOT_CONNECT
|| err
== ERROR_WINHTTP_TIMEOUT
))
223 skip("connection failed, skipping\n");
226 ok(ret
, "failed to send request %u\n", GetLastError());
228 setup_test( &info
, winhttp_receive_response
, __LINE__
);
229 ret
= WinHttpReceiveResponse( req
, NULL
);
230 ok(ret
, "failed to receive response %u\n", GetLastError());
232 size
= sizeof(status
);
233 ret
= WinHttpQueryHeaders( req
, WINHTTP_QUERY_STATUS_CODE
| WINHTTP_QUERY_FLAG_NUMBER
, NULL
, &status
, &size
, NULL
);
234 ok(ret
, "failed unexpectedly %u\n", GetLastError());
235 ok(status
== 200, "request failed unexpectedly %u\n", status
);
237 ResetEvent( info
.wait
);
238 setup_test( &info
, winhttp_close_handle
, __LINE__
);
239 WinHttpCloseHandle( req
);
240 WaitForSingleObject( info
.wait
, INFINITE
);
242 setup_test( &info
, winhttp_open_request
, __LINE__
);
243 req
= WinHttpOpenRequest( con
, NULL
, tests_hello_html
, NULL
, NULL
, NULL
, 0 );
244 ok(req
!= NULL
, "failed to open a request %u\n", GetLastError());
246 ret
= WinHttpSetOption( req
, WINHTTP_OPTION_CONTEXT_VALUE
, &context
, sizeof(struct info
*) );
247 ok(ret
, "failed to set context value %u\n", GetLastError());
249 setup_test( &info
, winhttp_send_request
, __LINE__
);
250 ret
= WinHttpSendRequest( req
, NULL
, 0, NULL
, 0, 0, 0 );
251 err
= GetLastError();
252 if (!ret
&& (err
== ERROR_WINHTTP_CANNOT_CONNECT
|| err
== ERROR_WINHTTP_TIMEOUT
))
254 skip("connection failed, skipping\n");
257 ok(ret
, "failed to send request %u\n", GetLastError());
259 setup_test( &info
, winhttp_receive_response
, __LINE__
);
260 ret
= WinHttpReceiveResponse( req
, NULL
);
261 ok(ret
, "failed to receive response %u\n", GetLastError());
263 size
= sizeof(status
);
264 ret
= WinHttpQueryHeaders( req
, WINHTTP_QUERY_STATUS_CODE
| WINHTTP_QUERY_FLAG_NUMBER
, NULL
, &status
, &size
, NULL
);
265 ok(ret
, "failed unexpectedly %u\n", GetLastError());
266 ok(status
== 200, "request failed unexpectedly %u\n", status
);
268 ResetEvent( info
.wait
);
269 setup_test( &info
, winhttp_close_handle
, __LINE__
);
270 WinHttpCloseHandle( req
);
271 WinHttpCloseHandle( req
);
272 WinHttpCloseHandle( con
);
273 WaitForSingleObject( info
.wait
, INFINITE
);
277 status
= WaitForSingleObject( event
, 0 );
278 ok(status
== WAIT_TIMEOUT
, "got %08x\n", status
);
281 setup_test( &info
, winhttp_close_handle
, __LINE__
);
282 WinHttpCloseHandle( ses
);
283 WaitForSingleObject( info
.wait
, INFINITE
);
287 status
= WaitForSingleObject( event
, 100 );
288 ok(status
== WAIT_OBJECT_0
, "got %08x\n", status
);
292 ses
= WinHttpOpen( user_agent
, 0, NULL
, NULL
, 0 );
293 ok(ses
!= NULL
, "failed to open session %u\n", GetLastError());
297 ret
= WinHttpSetOption( ses
, WINHTTP_OPTION_UNLOAD_NOTIFY_EVENT
, &event
, sizeof(event
) );
298 ok(ret
, "failed to set unload option\n");
301 WinHttpSetStatusCallback( ses
, check_notification
, WINHTTP_CALLBACK_FLAG_ALL_NOTIFICATIONS
, 0 );
303 ret
= WinHttpSetOption( ses
, WINHTTP_OPTION_CONTEXT_VALUE
, &context
, sizeof(struct info
*) );
304 ok(ret
, "failed to set context value %u\n", GetLastError());
306 setup_test( &info
, winhttp_connect
, __LINE__
);
307 con
= WinHttpConnect( ses
, test_winehq
, 0, 0 );
308 ok(con
!= NULL
, "failed to open a connection %u\n", GetLastError());
310 setup_test( &info
, winhttp_open_request
, __LINE__
);
311 req
= WinHttpOpenRequest( con
, NULL
, tests_hello_html
, NULL
, NULL
, NULL
, 0 );
312 ok(req
!= NULL
, "failed to open a request %u\n", GetLastError());
314 ret
= WinHttpSetOption( req
, WINHTTP_OPTION_CONTEXT_VALUE
, &context
, sizeof(struct info
*) );
315 ok(ret
, "failed to set context value %u\n", GetLastError());
317 setup_test( &info
, winhttp_send_request
, __LINE__
);
318 ret
= WinHttpSendRequest( req
, NULL
, 0, NULL
, 0, 0, 0 );
319 err
= GetLastError();
320 if (!ret
&& (err
== ERROR_WINHTTP_CANNOT_CONNECT
|| err
== ERROR_WINHTTP_TIMEOUT
))
322 skip("connection failed, skipping\n");
325 ok(ret
, "failed to send request %u\n", GetLastError());
327 setup_test( &info
, winhttp_receive_response
, __LINE__
);
328 ret
= WinHttpReceiveResponse( req
, NULL
);
329 ok(ret
, "failed to receive response %u\n", GetLastError());
331 size
= sizeof(status
);
332 ret
= WinHttpQueryHeaders( req
, WINHTTP_QUERY_STATUS_CODE
| WINHTTP_QUERY_FLAG_NUMBER
, NULL
, &status
, &size
, NULL
);
333 ok(ret
, "failed unexpectedly %u\n", GetLastError());
334 ok(status
== 200, "request failed unexpectedly %u\n", status
);
336 ResetEvent( info
.wait
);
337 setup_test( &info
, winhttp_close_handle
, __LINE__
);
338 WinHttpCloseHandle( req
);
339 WaitForSingleObject( info
.wait
, INFINITE
);
341 setup_test( &info
, winhttp_open_request
, __LINE__
);
342 req
= WinHttpOpenRequest( con
, NULL
, tests_hello_html
, NULL
, NULL
, NULL
, 0 );
343 ok(req
!= NULL
, "failed to open a request %u\n", GetLastError());
345 ret
= WinHttpSetOption( req
, WINHTTP_OPTION_CONTEXT_VALUE
, &context
, sizeof(struct info
*) );
346 ok(ret
, "failed to set context value %u\n", GetLastError());
348 setup_test( &info
, winhttp_send_request
, __LINE__
);
349 ret
= WinHttpSendRequest( req
, NULL
, 0, NULL
, 0, 0, 0 );
350 err
= GetLastError();
351 if (!ret
&& (err
== ERROR_WINHTTP_CANNOT_CONNECT
|| err
== ERROR_WINHTTP_TIMEOUT
))
353 skip("connection failed, skipping\n");
356 ok(ret
, "failed to send request %u\n", GetLastError());
358 setup_test( &info
, winhttp_receive_response
, __LINE__
);
359 ret
= WinHttpReceiveResponse( req
, NULL
);
360 ok(ret
, "failed to receive response %u\n", GetLastError());
362 size
= sizeof(status
);
363 ret
= WinHttpQueryHeaders( req
, WINHTTP_QUERY_STATUS_CODE
| WINHTTP_QUERY_FLAG_NUMBER
, NULL
, &status
, &size
, NULL
);
364 ok(ret
, "failed unexpectedly %u\n", GetLastError());
365 ok(status
== 200, "request failed unexpectedly %u\n", status
);
367 setup_test( &info
, winhttp_close_handle
, __LINE__
);
369 WinHttpCloseHandle( req
);
370 WinHttpCloseHandle( con
);
371 WaitForSingleObject( info
.wait
, INFINITE
);
375 status
= WaitForSingleObject( event
, 0 );
376 ok(status
== WAIT_TIMEOUT
, "got %08x\n", status
);
379 setup_test( &info
, winhttp_close_handle
, __LINE__
);
380 WinHttpCloseHandle( ses
);
381 WaitForSingleObject( info
.wait
, INFINITE
);
382 CloseHandle( info
.wait
);
383 end_test( &info
, __LINE__
);
387 status
= WaitForSingleObject( event
, 100 );
388 ok(status
== WAIT_OBJECT_0
, "got %08x\n", status
);
391 CloseHandle( event
);
394 static const struct notification redirect_test
[] =
396 { winhttp_connect
, WINHTTP_CALLBACK_STATUS_HANDLE_CREATED
},
397 { winhttp_open_request
, WINHTTP_CALLBACK_STATUS_HANDLE_CREATED
},
398 { winhttp_send_request
, WINHTTP_CALLBACK_STATUS_RESOLVING_NAME
, NF_WINE_ALLOW
},
399 { winhttp_send_request
, WINHTTP_CALLBACK_STATUS_NAME_RESOLVED
, NF_WINE_ALLOW
},
400 { winhttp_send_request
, WINHTTP_CALLBACK_STATUS_CONNECTING_TO_SERVER
, NF_WINE_ALLOW
},
401 { winhttp_send_request
, WINHTTP_CALLBACK_STATUS_CONNECTED_TO_SERVER
, NF_WINE_ALLOW
},
402 { winhttp_send_request
, WINHTTP_CALLBACK_STATUS_SENDING_REQUEST
},
403 { winhttp_send_request
, WINHTTP_CALLBACK_STATUS_REQUEST_SENT
},
404 { winhttp_receive_response
, WINHTTP_CALLBACK_STATUS_RECEIVING_RESPONSE
},
405 { winhttp_receive_response
, WINHTTP_CALLBACK_STATUS_RESPONSE_RECEIVED
},
406 { winhttp_receive_response
, WINHTTP_CALLBACK_STATUS_REDIRECT
},
407 { winhttp_receive_response
, WINHTTP_CALLBACK_STATUS_RESOLVING_NAME
, NF_ALLOW
},
408 { winhttp_receive_response
, WINHTTP_CALLBACK_STATUS_NAME_RESOLVED
, NF_ALLOW
},
409 { winhttp_receive_response
, WINHTTP_CALLBACK_STATUS_CONNECTING_TO_SERVER
, NF_ALLOW
},
410 { winhttp_receive_response
, WINHTTP_CALLBACK_STATUS_CONNECTED_TO_SERVER
, NF_ALLOW
},
411 { winhttp_receive_response
, WINHTTP_CALLBACK_STATUS_SENDING_REQUEST
},
412 { winhttp_receive_response
, WINHTTP_CALLBACK_STATUS_REQUEST_SENT
},
413 { winhttp_receive_response
, WINHTTP_CALLBACK_STATUS_RECEIVING_RESPONSE
},
414 { winhttp_receive_response
, WINHTTP_CALLBACK_STATUS_RESPONSE_RECEIVED
},
415 { winhttp_close_handle
, WINHTTP_CALLBACK_STATUS_CLOSING_CONNECTION
, NF_WINE_ALLOW
},
416 { winhttp_close_handle
, WINHTTP_CALLBACK_STATUS_CONNECTION_CLOSED
, NF_WINE_ALLOW
},
417 { winhttp_close_handle
, WINHTTP_CALLBACK_STATUS_HANDLE_CLOSING
},
418 { winhttp_close_handle
, WINHTTP_CALLBACK_STATUS_HANDLE_CLOSING
},
419 { winhttp_close_handle
, WINHTTP_CALLBACK_STATUS_HANDLE_CLOSING
, NF_SIGNAL
}
422 static void test_redirect( void )
424 HANDLE ses
, con
, req
;
425 DWORD size
, status
, err
;
427 struct info info
, *context
= &info
;
429 info
.test
= redirect_test
;
430 info
.count
= sizeof(redirect_test
) / sizeof(redirect_test
[0]);
432 info
.wait
= CreateEventW( NULL
, FALSE
, FALSE
, NULL
);
434 ses
= WinHttpOpen( user_agent
, 0, NULL
, NULL
, 0 );
435 ok(ses
!= NULL
, "failed to open session %u\n", GetLastError());
437 WinHttpSetStatusCallback( ses
, check_notification
, WINHTTP_CALLBACK_FLAG_ALL_NOTIFICATIONS
, 0 );
439 ret
= WinHttpSetOption( ses
, WINHTTP_OPTION_CONTEXT_VALUE
, &context
, sizeof(struct info
*) );
440 ok(ret
, "failed to set context value %u\n", GetLastError());
442 setup_test( &info
, winhttp_connect
, __LINE__
);
443 con
= WinHttpConnect( ses
, test_winehq
, 0, 0 );
444 ok(con
!= NULL
, "failed to open a connection %u\n", GetLastError());
446 setup_test( &info
, winhttp_open_request
, __LINE__
);
447 req
= WinHttpOpenRequest( con
, NULL
, tests_redirect
, NULL
, NULL
, NULL
, 0 );
448 ok(req
!= NULL
, "failed to open a request %u\n", GetLastError());
450 setup_test( &info
, winhttp_send_request
, __LINE__
);
451 ret
= WinHttpSendRequest( req
, NULL
, 0, NULL
, 0, 0, 0 );
452 err
= GetLastError();
453 if (!ret
&& (err
== ERROR_WINHTTP_CANNOT_CONNECT
|| err
== ERROR_WINHTTP_TIMEOUT
))
455 skip("connection failed, skipping\n");
458 ok(ret
, "failed to send request %u\n", GetLastError());
460 setup_test( &info
, winhttp_receive_response
, __LINE__
);
461 ret
= WinHttpReceiveResponse( req
, NULL
);
462 ok(ret
, "failed to receive response %u\n", GetLastError());
464 size
= sizeof(status
);
465 ret
= WinHttpQueryHeaders( req
, WINHTTP_QUERY_STATUS_CODE
| WINHTTP_QUERY_FLAG_NUMBER
, NULL
, &status
, &size
, NULL
);
466 ok(ret
, "failed unexpectedly %u\n", GetLastError());
467 ok(status
== 200, "request failed unexpectedly %u\n", status
);
469 setup_test( &info
, winhttp_close_handle
, __LINE__
);
471 WinHttpCloseHandle( req
);
472 WinHttpCloseHandle( con
);
473 WinHttpCloseHandle( ses
);
474 WaitForSingleObject( info
.wait
, INFINITE
);
475 CloseHandle( info
.wait
);
476 end_test( &info
, __LINE__
);
479 static const struct notification async_test
[] =
481 { winhttp_connect
, WINHTTP_CALLBACK_STATUS_HANDLE_CREATED
},
482 { winhttp_open_request
, WINHTTP_CALLBACK_STATUS_HANDLE_CREATED
},
483 { winhttp_send_request
, WINHTTP_CALLBACK_STATUS_RESOLVING_NAME
, NF_WINE_ALLOW
},
484 { winhttp_send_request
, WINHTTP_CALLBACK_STATUS_NAME_RESOLVED
, NF_WINE_ALLOW
},
485 { winhttp_send_request
, WINHTTP_CALLBACK_STATUS_CONNECTING_TO_SERVER
, NF_WINE_ALLOW
},
486 { winhttp_send_request
, WINHTTP_CALLBACK_STATUS_CONNECTED_TO_SERVER
, NF_WINE_ALLOW
},
487 { winhttp_send_request
, WINHTTP_CALLBACK_STATUS_SENDING_REQUEST
},
488 { winhttp_send_request
, WINHTTP_CALLBACK_STATUS_REQUEST_SENT
},
489 { winhttp_send_request
, WINHTTP_CALLBACK_STATUS_SENDREQUEST_COMPLETE
, NF_SIGNAL
},
490 { winhttp_receive_response
, WINHTTP_CALLBACK_STATUS_RECEIVING_RESPONSE
},
491 { winhttp_receive_response
, WINHTTP_CALLBACK_STATUS_RESPONSE_RECEIVED
},
492 { winhttp_receive_response
, WINHTTP_CALLBACK_STATUS_HEADERS_AVAILABLE
, NF_SIGNAL
},
493 { winhttp_query_data
, WINHTTP_CALLBACK_STATUS_DATA_AVAILABLE
, NF_SIGNAL
},
494 { winhttp_read_data
, WINHTTP_CALLBACK_STATUS_RECEIVING_RESPONSE
, NF_ALLOW
},
495 { winhttp_read_data
, WINHTTP_CALLBACK_STATUS_RESPONSE_RECEIVED
, NF_ALLOW
},
496 { winhttp_read_data
, WINHTTP_CALLBACK_STATUS_READ_COMPLETE
, NF_SIGNAL
},
497 { winhttp_close_handle
, WINHTTP_CALLBACK_STATUS_HANDLE_CLOSING
},
498 { winhttp_close_handle
, WINHTTP_CALLBACK_STATUS_HANDLE_CLOSING
},
499 { winhttp_close_handle
, WINHTTP_CALLBACK_STATUS_HANDLE_CLOSING
, NF_SIGNAL
}
502 static void test_async( void )
504 HANDLE ses
, con
, req
, event
;
505 DWORD size
, status
, err
;
506 BOOL ret
, unload
= TRUE
;
507 struct info info
, *context
= &info
;
510 info
.test
= async_test
;
511 info
.count
= sizeof(async_test
) / sizeof(async_test
[0]);
513 info
.wait
= CreateEventW( NULL
, FALSE
, FALSE
, NULL
);
515 ses
= WinHttpOpen( user_agent
, 0, NULL
, NULL
, WINHTTP_FLAG_ASYNC
);
516 ok(ses
!= NULL
, "failed to open session %u\n", GetLastError());
518 event
= CreateEventW( NULL
, FALSE
, FALSE
, NULL
);
519 ret
= WinHttpSetOption( ses
, WINHTTP_OPTION_UNLOAD_NOTIFY_EVENT
, &event
, sizeof(event
) );
522 win_skip("Unload event not supported\n");
526 SetLastError( 0xdeadbeef );
527 WinHttpSetStatusCallback( ses
, check_notification
, WINHTTP_CALLBACK_FLAG_ALL_NOTIFICATIONS
, 0 );
528 err
= GetLastError();
529 ok(err
== ERROR_SUCCESS
|| broken(err
== 0xdeadbeef) /* < win7 */, "got %u\n", err
);
531 SetLastError( 0xdeadbeef );
532 ret
= WinHttpSetOption( ses
, WINHTTP_OPTION_CONTEXT_VALUE
, &context
, sizeof(struct info
*) );
533 err
= GetLastError();
534 ok(ret
, "failed to set context value %u\n", err
);
535 ok(err
== ERROR_SUCCESS
|| broken(err
== 0xdeadbeef) /* < win7 */, "got %u\n", err
);
537 setup_test( &info
, winhttp_connect
, __LINE__
);
538 SetLastError( 0xdeadbeef );
539 con
= WinHttpConnect( ses
, test_winehq
, 0, 0 );
540 err
= GetLastError();
541 ok(con
!= NULL
, "failed to open a connection %u\n", err
);
542 ok(err
== ERROR_SUCCESS
|| broken(err
== WSAEINVAL
) /* < win7 */, "got %u\n", err
);
544 setup_test( &info
, winhttp_open_request
, __LINE__
);
545 SetLastError( 0xdeadbeef );
546 req
= WinHttpOpenRequest( con
, NULL
, tests_hello_html
, NULL
, NULL
, NULL
, 0 );
547 err
= GetLastError();
548 ok(req
!= NULL
, "failed to open a request %u\n", err
);
549 ok(err
== ERROR_SUCCESS
, "got %u\n", err
);
551 setup_test( &info
, winhttp_send_request
, __LINE__
);
552 SetLastError( 0xdeadbeef );
553 ret
= WinHttpSendRequest( req
, NULL
, 0, NULL
, 0, 0, 0 );
554 err
= GetLastError();
555 if (!ret
&& (err
== ERROR_WINHTTP_CANNOT_CONNECT
|| err
== ERROR_WINHTTP_TIMEOUT
))
557 skip("connection failed, skipping\n");
558 WinHttpCloseHandle( req
);
559 WinHttpCloseHandle( con
);
560 WinHttpCloseHandle( ses
);
561 CloseHandle( info
.wait
);
564 ok(ret
, "failed to send request %u\n", err
);
565 ok(err
== ERROR_SUCCESS
, "got %u\n", err
);
567 WaitForSingleObject( info
.wait
, INFINITE
);
569 setup_test( &info
, winhttp_receive_response
, __LINE__
);
570 SetLastError( 0xdeadbeef );
571 ret
= WinHttpReceiveResponse( req
, NULL
);
572 err
= GetLastError();
573 ok(ret
, "failed to receive response %u\n", err
);
574 ok(err
== ERROR_SUCCESS
, "got %u\n", err
);
576 WaitForSingleObject( info
.wait
, INFINITE
);
578 size
= sizeof(status
);
579 SetLastError( 0xdeadbeef );
580 ret
= WinHttpQueryHeaders( req
, WINHTTP_QUERY_STATUS_CODE
| WINHTTP_QUERY_FLAG_NUMBER
, NULL
, &status
, &size
, NULL
);
581 err
= GetLastError();
582 ok(ret
, "failed unexpectedly %u\n", err
);
583 ok(status
== 200, "request failed unexpectedly %u\n", status
);
584 ok(err
== ERROR_SUCCESS
|| broken(err
== 0xdeadbeef) /* < win7 */, "got %u\n", err
);
586 setup_test( &info
, winhttp_query_data
, __LINE__
);
587 SetLastError( 0xdeadbeef );
588 ret
= WinHttpQueryDataAvailable( req
, NULL
);
589 err
= GetLastError();
590 ok(ret
, "failed to query data available %u\n", err
);
591 ok(err
== ERROR_SUCCESS
|| err
== ERROR_IO_PENDING
|| broken(err
== 0xdeadbeef) /* < win7 */, "got %u\n", err
);
593 WaitForSingleObject( info
.wait
, INFINITE
);
595 setup_test( &info
, winhttp_read_data
, __LINE__
);
596 ret
= WinHttpReadData( req
, buffer
, sizeof(buffer
), NULL
);
597 ok(ret
, "failed to read data %u\n", err
);
599 WaitForSingleObject( info
.wait
, INFINITE
);
601 setup_test( &info
, winhttp_close_handle
, __LINE__
);
602 WinHttpCloseHandle( req
);
603 WinHttpCloseHandle( con
);
607 status
= WaitForSingleObject( event
, 0 );
608 ok(status
== WAIT_TIMEOUT
, "got %08x\n", status
);
610 WinHttpCloseHandle( ses
);
611 WaitForSingleObject( info
.wait
, INFINITE
);
612 end_test( &info
, __LINE__
);
616 status
= WaitForSingleObject( event
, 2000 );
617 ok(status
== WAIT_OBJECT_0
, "got %08x\n", status
);
619 CloseHandle( event
);
620 CloseHandle( info
.wait
);
621 end_test( &info
, __LINE__
);
624 static const char okmsg
[] =
625 "HTTP/1.1 200 OK\r\n"
626 "Server: winetest\r\n"
629 static const char page1
[] =
631 "<HEAD><TITLE>winhttp test page</TITLE></HEAD>\r\n"
632 "<BODY>The quick brown fox jumped over the lazy dog<P></BODY>\r\n"
641 static int server_socket
;
642 static HANDLE server_socket_available
, server_socket_done
;
644 static DWORD CALLBACK
server_thread(LPVOID param
)
646 struct server_info
*si
= param
;
647 int r
, c
= -1, i
, on
;
649 struct sockaddr_in sa
;
652 int last_request
= 0;
654 WSAStartup(MAKEWORD(1,1), &wsaData
);
656 s
= socket(AF_INET
, SOCK_STREAM
, 0);
657 if (s
== INVALID_SOCKET
)
661 setsockopt(s
, SOL_SOCKET
, SO_REUSEADDR
, (char*)&on
, sizeof on
);
663 memset(&sa
, 0, sizeof sa
);
664 sa
.sin_family
= AF_INET
;
665 sa
.sin_port
= htons(si
->port
);
666 sa
.sin_addr
.S_un
.S_addr
= inet_addr("127.0.0.1");
668 r
= bind(s
, (struct sockaddr
*)&sa
, sizeof(sa
));
676 if (c
== -1) c
= accept(s
, NULL
, NULL
);
678 memset(buffer
, 0, sizeof buffer
);
679 for(i
= 0; i
< sizeof buffer
- 1; i
++)
681 r
= recv(c
, &buffer
[i
], 1, 0);
685 if (buffer
[i
- 2] == '\n' && buffer
[i
] == '\n' &&
686 buffer
[i
- 3] == '\r' && buffer
[i
- 1] == '\r')
689 if (strstr(buffer
, "GET /quit"))
691 send(c
, okmsg
, sizeof okmsg
- 1, 0);
692 send(c
, page1
, sizeof page1
- 1, 0);
695 else if(strstr(buffer
, "GET /socket"))
698 SetEvent(server_socket_available
);
699 WaitForSingleObject(server_socket_done
, INFINITE
);
700 ResetEvent(server_socket_available
);
705 } while (!last_request
);
711 static void test_basic_request(int port
, const WCHAR
*verb
, const WCHAR
*path
)
713 HINTERNET ses
, con
, req
;
715 DWORD count
, status
, size
;
718 ses
= WinHttpOpen(NULL
, WINHTTP_ACCESS_TYPE_NO_PROXY
, NULL
, NULL
, 0);
719 ok(ses
!= NULL
, "failed to open session %u\n", GetLastError());
721 con
= WinHttpConnect(ses
, localhostW
, port
, 0);
722 ok(con
!= NULL
, "failed to open a connection %u\n", GetLastError());
724 req
= WinHttpOpenRequest(con
, verb
, path
, NULL
, NULL
, NULL
, 0);
725 ok(req
!= NULL
, "failed to open a request %u\n", GetLastError());
727 ret
= WinHttpSendRequest(req
, NULL
, 0, NULL
, 0, 0, 0);
728 ok(ret
, "failed to send request %u\n", GetLastError());
730 ret
= WinHttpReceiveResponse(req
, NULL
);
731 ok(ret
, "failed to receive response %u\n", GetLastError());
734 size
= sizeof(status
);
735 ret
= WinHttpQueryHeaders(req
, WINHTTP_QUERY_STATUS_CODE
|WINHTTP_QUERY_FLAG_NUMBER
, NULL
, &status
, &size
, NULL
);
736 ok(ret
, "failed to query status code %u\n", GetLastError());
737 ok(status
== HTTP_STATUS_OK
, "request failed unexpectedly %u\n", status
);
740 memset(buffer
, 0, sizeof(buffer
));
741 ret
= WinHttpReadData(req
, buffer
, sizeof buffer
, &count
);
742 ok(ret
, "failed to read data %u\n", GetLastError());
743 ok(count
== sizeof page1
- 1, "count was wrong\n");
744 ok(!memcmp(buffer
, page1
, sizeof page1
), "http data wrong\n");
746 WinHttpCloseHandle(req
);
747 WinHttpCloseHandle(con
);
748 WinHttpCloseHandle(ses
);
751 static const struct notification open_socket_request_test
[] =
753 { winhttp_connect
, WINHTTP_CALLBACK_STATUS_HANDLE_CREATED
},
754 { winhttp_open_request
, WINHTTP_CALLBACK_STATUS_HANDLE_CREATED
},
755 { winhttp_send_request
, WINHTTP_CALLBACK_STATUS_RESOLVING_NAME
},
756 { winhttp_send_request
, WINHTTP_CALLBACK_STATUS_NAME_RESOLVED
},
757 { winhttp_send_request
, WINHTTP_CALLBACK_STATUS_CONNECTING_TO_SERVER
},
758 { winhttp_send_request
, WINHTTP_CALLBACK_STATUS_CONNECTING_TO_SERVER
, NF_ALLOW
}, /* some versions call it twice. why? */
759 { winhttp_send_request
, WINHTTP_CALLBACK_STATUS_CONNECTED_TO_SERVER
},
760 { winhttp_send_request
, WINHTTP_CALLBACK_STATUS_SENDING_REQUEST
},
761 { winhttp_send_request
, WINHTTP_CALLBACK_STATUS_REQUEST_SENT
},
762 { winhttp_send_request
, WINHTTP_CALLBACK_STATUS_SENDREQUEST_COMPLETE
, NF_SIGNAL
}
765 static const struct notification reuse_socket_request_test
[] =
767 { winhttp_connect
, WINHTTP_CALLBACK_STATUS_HANDLE_CREATED
},
768 { winhttp_open_request
, WINHTTP_CALLBACK_STATUS_HANDLE_CREATED
},
769 { winhttp_send_request
, WINHTTP_CALLBACK_STATUS_SENDING_REQUEST
},
770 { winhttp_send_request
, WINHTTP_CALLBACK_STATUS_REQUEST_SENT
},
771 { winhttp_send_request
, WINHTTP_CALLBACK_STATUS_SENDREQUEST_COMPLETE
, NF_SIGNAL
},
774 static void open_async_request(int port
, struct test_request
*req
, struct info
*info
, const WCHAR
*path
, BOOL reuse_connection
)
779 if (reuse_connection
)
781 info
->test
= reuse_socket_request_test
;
782 info
->count
= sizeof(reuse_socket_request_test
) / sizeof(reuse_socket_request_test
[0]);
786 info
->test
= open_socket_request_test
;
787 info
->count
= sizeof(open_socket_request_test
) / sizeof(open_socket_request_test
[0]);
790 req
->session
= WinHttpOpen( user_agent
, 0, NULL
, NULL
, WINHTTP_FLAG_ASYNC
);
791 ok(req
->session
!= NULL
, "failed to open session %u\n", GetLastError());
793 WinHttpSetOption( req
->session
, WINHTTP_OPTION_CONTEXT_VALUE
, &info
, sizeof(struct info
*) );
794 WinHttpSetStatusCallback( req
->session
, check_notification
, WINHTTP_CALLBACK_FLAG_ALL_NOTIFICATIONS
, 0 );
796 setup_test( info
, winhttp_connect
, __LINE__
);
797 req
->connection
= WinHttpConnect( req
->session
, localhostW
, port
, 0 );
798 ok(req
->connection
!= NULL
, "failed to open a connection %u\n", GetLastError());
800 setup_test( info
, winhttp_open_request
, __LINE__
);
801 req
->request
= WinHttpOpenRequest( req
->connection
, NULL
, path
, NULL
, NULL
, NULL
, 0 );
802 ok(req
->request
!= NULL
, "failed to open a request %u\n", GetLastError());
804 setup_test( info
, winhttp_send_request
, __LINE__
);
805 ret
= WinHttpSendRequest( req
->request
, NULL
, 0, NULL
, 0, 0, 0 );
806 ok(ret
, "failed to send request %u\n", GetLastError());
809 static void open_socket_request(int port
, struct test_request
*req
, struct info
*info
)
811 static const WCHAR socketW
[] = {'/','s','o','c','k','e','t',0};
813 ResetEvent( server_socket_done
);
814 open_async_request( port
, req
, info
, socketW
, FALSE
);
815 WaitForSingleObject( server_socket_available
, INFINITE
);
818 static const struct notification server_reply_test
[] =
820 { winhttp_send_request
, WINHTTP_CALLBACK_STATUS_RECEIVING_RESPONSE
, NF_ALLOW
},
821 { winhttp_send_request
, WINHTTP_CALLBACK_STATUS_RESPONSE_RECEIVED
, NF_ALLOW
},
822 { winhttp_send_request
, WINHTTP_CALLBACK_STATUS_HEADERS_AVAILABLE
, NF_SIGNAL
}
825 static void server_send_reply(struct test_request
*req
, struct info
*info
, const char *msg
)
829 send( server_socket
, msg
, strlen( msg
), 0 );
830 WaitForSingleObject( info
->wait
, INFINITE
);
832 info
->test
= server_reply_test
;
833 info
->count
= sizeof(server_reply_test
) / sizeof(server_reply_test
[0]);
835 setup_test( info
, winhttp_send_request
, __LINE__
);
836 ret
= WinHttpReceiveResponse( req
->request
, NULL
);
837 ok(ret
, "failed to receive response %u\n", GetLastError());
839 WaitForSingleObject( info
->wait
, INFINITE
);
840 end_test( info
, __LINE__
);
843 #define server_read_data(a) _server_read_data(a,__LINE__)
844 static void _server_read_data(const char *expect_prefix
, unsigned int line
)
849 size
= recv( server_socket
, buf
, sizeof(buf
), 0 );
850 len
= strlen( expect_prefix
);
851 ok_(__FILE__
,line
)(size
> len
, "data too short\n");
855 ok_(__FILE__
,line
)(!strcmp( buf
, expect_prefix
), "unexpected data \"%s\"\n", buf
);
859 static const struct notification close_request_test
[] =
861 { winhttp_close_handle
, WINHTTP_CALLBACK_STATUS_HANDLE_CLOSING
},
862 { winhttp_close_handle
, WINHTTP_CALLBACK_STATUS_HANDLE_CLOSING
},
863 { winhttp_close_handle
, WINHTTP_CALLBACK_STATUS_HANDLE_CLOSING
, NF_SIGNAL
}
866 static const struct notification close_allow_connection_close_request_test
[] =
868 { winhttp_close_handle
, WINHTTP_CALLBACK_STATUS_CLOSING_CONNECTION
, NF_ALLOW
},
869 { winhttp_close_handle
, WINHTTP_CALLBACK_STATUS_CONNECTION_CLOSED
, NF_ALLOW
},
870 { winhttp_close_handle
, WINHTTP_CALLBACK_STATUS_HANDLE_CLOSING
},
871 { winhttp_close_handle
, WINHTTP_CALLBACK_STATUS_HANDLE_CLOSING
},
872 { winhttp_close_handle
, WINHTTP_CALLBACK_STATUS_HANDLE_CLOSING
, NF_SIGNAL
}
875 static void close_request(struct test_request
*req
, struct info
*info
, BOOL allow_closing_connection
)
879 if (allow_closing_connection
)
881 info
->test
= close_allow_connection_close_request_test
;
882 info
->count
= sizeof(close_allow_connection_close_request_test
)/sizeof(*close_allow_connection_close_request_test
);
886 info
->test
= close_request_test
;
887 info
->count
= sizeof(close_request_test
)/sizeof(*close_request_test
);
890 setup_test( info
, winhttp_close_handle
, __LINE__
);
892 ret
= WinHttpCloseHandle( req
->request
);
893 ok(ret
, "WinHttpCloseHandle failed: %u\n", GetLastError());
894 ret
= WinHttpCloseHandle( req
->connection
);
895 ok(ret
, "WinHttpCloseHandle failed: %u\n", GetLastError());
896 ret
= WinHttpCloseHandle( req
->session
);
897 ok(ret
, "WinHttpCloseHandle failed: %u\n", GetLastError());
899 WaitForSingleObject( info
->wait
, INFINITE
);
900 end_test( info
, __LINE__
);
903 static const struct notification read_test
[] =
905 { winhttp_read_data
, WINHTTP_CALLBACK_STATUS_RECEIVING_RESPONSE
, NF_ALLOW
},
906 { winhttp_read_data
, WINHTTP_CALLBACK_STATUS_RESPONSE_RECEIVED
, NF_ALLOW
},
907 { winhttp_read_data
, WINHTTP_CALLBACK_STATUS_READ_COMPLETE
, NF_SIGNAL
}
910 static const struct notification read_allow_close_test
[] =
912 { winhttp_read_data
, WINHTTP_CALLBACK_STATUS_RECEIVING_RESPONSE
, NF_ALLOW
},
913 { winhttp_read_data
, WINHTTP_CALLBACK_STATUS_RESPONSE_RECEIVED
, NF_ALLOW
},
914 { winhttp_read_data
, WINHTTP_CALLBACK_STATUS_CLOSING_CONNECTION
, NF_ALLOW
},
915 { winhttp_read_data
, WINHTTP_CALLBACK_STATUS_CONNECTION_CLOSED
, NF_ALLOW
},
916 { winhttp_read_data
, WINHTTP_CALLBACK_STATUS_READ_COMPLETE
, NF_SIGNAL
}
919 #define read_request_data(a,b,c,d) _read_request_data(a,b,c,d,__LINE__)
920 static void _read_request_data(struct test_request
*req
, struct info
*info
, const char *expected_data
, BOOL closing_connection
, unsigned line
)
926 if (closing_connection
)
928 info
->test
= read_allow_close_test
;
929 info
->count
= sizeof(read_allow_close_test
)/sizeof(*read_allow_close_test
);
933 info
->test
= read_test
;
934 info
->count
= sizeof(read_test
)/sizeof(*read_test
);
938 setup_test( info
, winhttp_read_data
, line
);
939 memset(buffer
, '?', sizeof(buffer
));
941 ret
= WinHttpReadData( req
->request
, buffer
, sizeof(buffer
), &read
);
942 ok(ret
, "failed to read data %u\n", GetLastError());
944 WaitForSingleObject( info
->wait
, INFINITE
);
946 len
= strlen(expected_data
);
947 ok(!memcmp(buffer
, expected_data
, len
), "unexpeceted data\n");
950 static void test_persistent_connection(int port
)
952 struct test_request req
;
955 static const WCHAR testW
[] = {'/','t','e','s','t',0};
957 trace("Testing persistent connection...\n");
959 info
.wait
= CreateEventW( NULL
, FALSE
, FALSE
, NULL
);
961 open_socket_request( port
, &req
, &info
);
962 server_send_reply( &req
, &info
,
963 "HTTP/1.1 200 OK\r\n"
964 "Server: winetest\r\n"
965 "Connection: keep-alive\r\n"
966 "Content-Length: 1\r\n"
969 read_request_data( &req
, &info
, "X", FALSE
);
970 close_request( &req
, &info
, FALSE
);
972 /* chunked connection test */
973 open_async_request( port
, &req
, &info
, testW
, TRUE
);
974 server_read_data( "GET /test HTTP/1.1\r\n" );
975 server_send_reply( &req
, &info
,
976 "HTTP/1.1 200 OK\r\n"
977 "Server: winetest\r\n"
978 "Transfer-Encoding: chunked\r\n"
979 "Connection: keep-alive\r\n"
983 read_request_data( &req
, &info
, "123456789", FALSE
);
984 close_request( &req
, &info
, FALSE
);
986 /* HTTP/1.1 connections are persistent by default, no additional header is needed */
987 open_async_request( port
, &req
, &info
, testW
, 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"
995 read_request_data( &req
, &info
, "xx", FALSE
);
996 close_request( &req
, &info
, FALSE
);
998 open_async_request( port
, &req
, &info
, testW
, TRUE
);
999 server_read_data( "GET /test HTTP/1.1\r\n" );
1000 server_send_reply( &req
, &info
,
1001 "HTTP/1.1 200 OK\r\n"
1002 "Server: winetest\r\n"
1003 "Content-Length: 2\r\n"
1004 "Connection: close\r\n"
1007 close_request( &req
, &info
, TRUE
);
1009 SetEvent( server_socket_done
);
1010 CloseHandle( info
.wait
);
1013 START_TEST (notification
)
1015 static const WCHAR quitW
[] = {'/','q','u','i','t',0};
1016 struct server_info si
;
1020 test_connection_cache();
1024 si
.event
= CreateEventW( NULL
, 0, 0, NULL
);
1027 thread
= CreateThread( NULL
, 0, server_thread
, (LPVOID
)&si
, 0, NULL
);
1028 ok(thread
!= NULL
, "failed to create thread %u\n", GetLastError());
1030 server_socket_available
= CreateEventW( NULL
, 0, 0, NULL
);
1031 server_socket_done
= CreateEventW( NULL
, 0, 0, NULL
);
1033 ret
= WaitForSingleObject( si
.event
, 10000 );
1034 ok(ret
== WAIT_OBJECT_0
, "failed to start winhttp test server %u\n", GetLastError());
1035 if (ret
!= WAIT_OBJECT_0
)
1038 test_persistent_connection( si
.port
);
1040 /* send the basic request again to shutdown the server thread */
1041 test_basic_request( si
.port
, NULL
, quitW
);
1043 WaitForSingleObject( thread
, 3000 );
1044 CloseHandle( thread
);
1045 CloseHandle( server_socket_available
);
1046 CloseHandle( server_socket_done
);