winhttp/tests: Add asynchronous WebSocket tests.
Signed-off-by: Hans Leidekker <hans@codeweavers.com> Signed-off-by: Alexandre Julliard <julliard@winehq.org>
This commit is contained in:
parent
3b1d18fd6e
commit
938b3e5771
|
@ -28,12 +28,24 @@
|
|||
|
||||
#include "wine/test.h"
|
||||
|
||||
static DWORD (WINAPI *pWinHttpWebSocketClose)(HINTERNET,USHORT,void*,DWORD);
|
||||
static HINTERNET (WINAPI *pWinHttpWebSocketCompleteUpgrade)(HINTERNET,DWORD_PTR);
|
||||
static DWORD (WINAPI *pWinHttpWebSocketQueryCloseStatus)(HINTERNET,USHORT*,void*,DWORD,DWORD*);
|
||||
static DWORD (WINAPI *pWinHttpWebSocketReceive)(HINTERNET,void*,DWORD,DWORD*,WINHTTP_WEB_SOCKET_BUFFER_TYPE*);
|
||||
static DWORD (WINAPI *pWinHttpWebSocketSend)(HINTERNET,WINHTTP_WEB_SOCKET_BUFFER_TYPE,void*,DWORD);
|
||||
static DWORD (WINAPI *pWinHttpWebSocketShutdown)(HINTERNET,USHORT,void*,DWORD);
|
||||
|
||||
enum api
|
||||
{
|
||||
winhttp_connect = 1,
|
||||
winhttp_open_request,
|
||||
winhttp_send_request,
|
||||
winhttp_receive_response,
|
||||
winhttp_websocket_complete_upgrade,
|
||||
winhttp_websocket_send,
|
||||
winhttp_websocket_receive,
|
||||
winhttp_websocket_shutdown,
|
||||
winhttp_websocket_close,
|
||||
winhttp_query_data,
|
||||
winhttp_read_data,
|
||||
winhttp_write_data,
|
||||
|
@ -615,6 +627,191 @@ static void test_async( void )
|
|||
end_test( &info, __LINE__ );
|
||||
}
|
||||
|
||||
static const struct notification websocket_test[] =
|
||||
{
|
||||
{ winhttp_connect, WINHTTP_CALLBACK_STATUS_HANDLE_CREATED },
|
||||
{ winhttp_open_request, WINHTTP_CALLBACK_STATUS_HANDLE_CREATED },
|
||||
{ winhttp_send_request, WINHTTP_CALLBACK_STATUS_RESOLVING_NAME },
|
||||
{ winhttp_send_request, WINHTTP_CALLBACK_STATUS_NAME_RESOLVED },
|
||||
{ winhttp_send_request, WINHTTP_CALLBACK_STATUS_CONNECTING_TO_SERVER },
|
||||
{ winhttp_send_request, WINHTTP_CALLBACK_STATUS_CONNECTED_TO_SERVER },
|
||||
{ winhttp_send_request, WINHTTP_CALLBACK_STATUS_SENDING_REQUEST },
|
||||
{ winhttp_send_request, WINHTTP_CALLBACK_STATUS_REQUEST_SENT },
|
||||
{ winhttp_send_request, WINHTTP_CALLBACK_STATUS_SENDREQUEST_COMPLETE, NF_SIGNAL },
|
||||
{ winhttp_receive_response, WINHTTP_CALLBACK_STATUS_RECEIVING_RESPONSE },
|
||||
{ winhttp_receive_response, WINHTTP_CALLBACK_STATUS_RESPONSE_RECEIVED },
|
||||
{ winhttp_receive_response, WINHTTP_CALLBACK_STATUS_HEADERS_AVAILABLE, NF_SIGNAL },
|
||||
{ winhttp_websocket_complete_upgrade, WINHTTP_CALLBACK_STATUS_HANDLE_CREATED, NF_SIGNAL },
|
||||
{ winhttp_websocket_send, WINHTTP_CALLBACK_STATUS_WRITE_COMPLETE, NF_SIGNAL },
|
||||
{ winhttp_websocket_receive, WINHTTP_CALLBACK_STATUS_READ_COMPLETE, NF_SIGNAL },
|
||||
{ winhttp_websocket_shutdown, WINHTTP_CALLBACK_STATUS_SHUTDOWN_COMPLETE, NF_SIGNAL },
|
||||
{ winhttp_websocket_close, WINHTTP_CALLBACK_STATUS_CLOSE_COMPLETE, NF_SIGNAL },
|
||||
{ winhttp_close_handle, WINHTTP_CALLBACK_STATUS_HANDLE_CLOSING },
|
||||
{ winhttp_close_handle, WINHTTP_CALLBACK_STATUS_CLOSING_CONNECTION, NF_WINE_ALLOW },
|
||||
{ winhttp_close_handle, WINHTTP_CALLBACK_STATUS_CONNECTION_CLOSED, NF_WINE_ALLOW },
|
||||
{ winhttp_close_handle, WINHTTP_CALLBACK_STATUS_HANDLE_CLOSING },
|
||||
{ winhttp_close_handle, WINHTTP_CALLBACK_STATUS_HANDLE_CLOSING },
|
||||
{ winhttp_close_handle, WINHTTP_CALLBACK_STATUS_HANDLE_CLOSING, NF_SIGNAL }
|
||||
};
|
||||
|
||||
static void test_websocket(void)
|
||||
{
|
||||
HANDLE session, connection, request, socket, event;
|
||||
WINHTTP_WEB_SOCKET_BUFFER_TYPE type;
|
||||
DWORD size, status, err;
|
||||
BOOL ret, unload = TRUE;
|
||||
struct info info, *context = &info;
|
||||
char buffer[1024];
|
||||
USHORT close_status;
|
||||
|
||||
if (!pWinHttpWebSocketCompleteUpgrade)
|
||||
{
|
||||
win_skip( "WinHttpWebSocketCompleteUpgrade not supported\n" );
|
||||
return;
|
||||
}
|
||||
|
||||
info.test = websocket_test;
|
||||
info.count = ARRAY_SIZE( websocket_test );
|
||||
info.index = 0;
|
||||
info.wait = CreateEventW( NULL, FALSE, FALSE, NULL );
|
||||
|
||||
session = WinHttpOpen( L"winetest", 0, NULL, NULL, WINHTTP_FLAG_ASYNC );
|
||||
ok( session != NULL, "got %u\n", GetLastError() );
|
||||
|
||||
event = CreateEventW( NULL, FALSE, FALSE, NULL );
|
||||
ret = WinHttpSetOption( session, WINHTTP_OPTION_UNLOAD_NOTIFY_EVENT, &event, sizeof(event) );
|
||||
if (!ret)
|
||||
{
|
||||
win_skip( "Unload event not supported\n" );
|
||||
unload = FALSE;
|
||||
}
|
||||
|
||||
SetLastError( 0xdeadbeef );
|
||||
WinHttpSetStatusCallback( session, check_notification, WINHTTP_CALLBACK_FLAG_ALL_NOTIFICATIONS, 0 );
|
||||
err = GetLastError();
|
||||
ok( err == ERROR_SUCCESS || broken(err == 0xdeadbeef) /* < win7 */, "got %u\n", err );
|
||||
|
||||
SetLastError( 0xdeadbeef );
|
||||
ret = WinHttpSetOption( session, WINHTTP_OPTION_CONTEXT_VALUE, &context, sizeof(context) );
|
||||
err = GetLastError();
|
||||
ok( ret, "got %u\n", err );
|
||||
ok( err == ERROR_SUCCESS || broken(err == 0xdeadbeef) /* < win7 */, "got %u\n", err);
|
||||
|
||||
setup_test( &info, winhttp_connect, __LINE__ );
|
||||
SetLastError( 0xdeadbeef );
|
||||
connection = WinHttpConnect( session, L"echo.websocket.org", 0, 0 );
|
||||
err = GetLastError();
|
||||
ok( connection != NULL, "got %u\n", err);
|
||||
ok( err == ERROR_SUCCESS || broken(err == WSAEINVAL) /* < win7 */, "got %u\n", err );
|
||||
|
||||
setup_test( &info, winhttp_open_request, __LINE__ );
|
||||
SetLastError( 0xdeadbeef );
|
||||
request = WinHttpOpenRequest( connection, NULL, L"/", NULL, NULL, NULL, 0 );
|
||||
err = GetLastError();
|
||||
ok( request != NULL, "got %u\n", err );
|
||||
ok( err == ERROR_SUCCESS, "got %u\n", err );
|
||||
|
||||
ret = WinHttpSetOption( request, WINHTTP_OPTION_UPGRADE_TO_WEB_SOCKET, NULL, 0 );
|
||||
ok( ret, "got %u\n", GetLastError() );
|
||||
|
||||
setup_test( &info, winhttp_send_request, __LINE__ );
|
||||
SetLastError( 0xdeadbeef );
|
||||
ret = WinHttpSendRequest( request, NULL, 0, NULL, 0, 0, 0 );
|
||||
err = GetLastError();
|
||||
if (!ret && (err == ERROR_WINHTTP_CANNOT_CONNECT || err == ERROR_WINHTTP_TIMEOUT))
|
||||
{
|
||||
skip( "connection failed, skipping\n" );
|
||||
WinHttpCloseHandle( request );
|
||||
WinHttpCloseHandle( connection );
|
||||
WinHttpCloseHandle( session );
|
||||
CloseHandle( info.wait );
|
||||
return;
|
||||
}
|
||||
ok( ret, "got %u\n", err );
|
||||
ok( err == ERROR_SUCCESS, "got %u\n", err );
|
||||
WaitForSingleObject( info.wait, INFINITE );
|
||||
|
||||
setup_test( &info, winhttp_receive_response, __LINE__ );
|
||||
SetLastError( 0xdeadbeef );
|
||||
ret = WinHttpReceiveResponse( request, NULL );
|
||||
err = GetLastError();
|
||||
ok( ret, "got %u\n", err );
|
||||
ok( err == ERROR_SUCCESS, "got %u\n", err );
|
||||
WaitForSingleObject( info.wait, INFINITE );
|
||||
|
||||
size = sizeof(status);
|
||||
SetLastError( 0xdeadbeef );
|
||||
ret = WinHttpQueryHeaders( request, WINHTTP_QUERY_STATUS_CODE|WINHTTP_QUERY_FLAG_NUMBER, NULL, &status, &size, NULL );
|
||||
err = GetLastError();
|
||||
ok( ret, "failed unexpectedly %u\n", err );
|
||||
ok( status == 101, "got %u\n", status );
|
||||
ok( err == ERROR_SUCCESS || broken(err == 0xdeadbeef) /* < win7 */, "got %u\n", err );
|
||||
|
||||
setup_test( &info, winhttp_websocket_complete_upgrade, __LINE__ );
|
||||
SetLastError( 0xdeadbeef );
|
||||
socket = pWinHttpWebSocketCompleteUpgrade( request, (DWORD_PTR)context );
|
||||
err = GetLastError();
|
||||
ok( socket != NULL, "got %u\n", err );
|
||||
ok( err == ERROR_SUCCESS, "got %u\n", err );
|
||||
WaitForSingleObject( info.wait, INFINITE );
|
||||
|
||||
setup_test( &info, winhttp_websocket_send, __LINE__ );
|
||||
err = pWinHttpWebSocketSend( socket, 0, (void *)"hello", sizeof("hello") );
|
||||
ok( err == ERROR_SUCCESS, "got %u\n", err );
|
||||
WaitForSingleObject( info.wait, INFINITE );
|
||||
|
||||
setup_test( &info, winhttp_websocket_receive, __LINE__ );
|
||||
buffer[0] = 0;
|
||||
size = 0xdeadbeef;
|
||||
type = 0xdeadbeef;
|
||||
err = pWinHttpWebSocketReceive( socket, buffer, sizeof(buffer), &size, &type );
|
||||
ok( err == ERROR_SUCCESS, "got %u\n", err );
|
||||
WaitForSingleObject( info.wait, INFINITE );
|
||||
ok( size == 0xdeadbeef, "got %u\n", size );
|
||||
ok( type == 0xdeadbeef, "got %u\n", type );
|
||||
ok( buffer[0], "unexpected data\n" );
|
||||
|
||||
setup_test( &info, winhttp_websocket_shutdown, __LINE__ );
|
||||
err = pWinHttpWebSocketShutdown( socket, 1000, (void *)"success", sizeof("success") );
|
||||
ok( err == ERROR_SUCCESS, "got %u\n", err );
|
||||
WaitForSingleObject( info.wait, INFINITE );
|
||||
|
||||
setup_test( &info, winhttp_websocket_close, __LINE__ );
|
||||
ret = pWinHttpWebSocketClose( socket, 1000, (void *)"success", sizeof("success") );
|
||||
ok( err == ERROR_SUCCESS, "got %u\n", err );
|
||||
WaitForSingleObject( info.wait, INFINITE );
|
||||
|
||||
close_status = 0xdead;
|
||||
size = sizeof(buffer) + 1;
|
||||
err = pWinHttpWebSocketQueryCloseStatus( socket, &close_status, buffer, sizeof(buffer), &size );
|
||||
ok( err == ERROR_SUCCESS, "got %u\n", err );
|
||||
ok( close_status == 1000, "got %u\n", close_status );
|
||||
ok( size <= sizeof(buffer), "got %u\n", size );
|
||||
|
||||
setup_test( &info, winhttp_close_handle, __LINE__ );
|
||||
WinHttpCloseHandle( socket );
|
||||
WinHttpCloseHandle( request );
|
||||
WinHttpCloseHandle( connection );
|
||||
|
||||
if (unload)
|
||||
{
|
||||
status = WaitForSingleObject( event, 0 );
|
||||
ok( status == WAIT_TIMEOUT, "got %08x\n", status );
|
||||
}
|
||||
WinHttpCloseHandle( session );
|
||||
WaitForSingleObject( info.wait, INFINITE );
|
||||
end_test( &info, __LINE__ );
|
||||
|
||||
if (unload)
|
||||
{
|
||||
status = WaitForSingleObject( event, 2000 );
|
||||
ok( status == WAIT_OBJECT_0, "got %08x\n", status );
|
||||
}
|
||||
CloseHandle( event );
|
||||
CloseHandle( info.wait );
|
||||
end_test( &info, __LINE__ );
|
||||
}
|
||||
|
||||
static const char okmsg[] =
|
||||
"HTTP/1.1 200 OK\r\n"
|
||||
"Server: winetest\r\n"
|
||||
|
@ -1001,13 +1198,22 @@ static void test_persistent_connection(int port)
|
|||
|
||||
START_TEST (notification)
|
||||
{
|
||||
HMODULE mod = GetModuleHandleA( "winhttp.dll" );
|
||||
struct server_info si;
|
||||
HANDLE thread;
|
||||
DWORD ret;
|
||||
|
||||
pWinHttpWebSocketClose = (void *)GetProcAddress( mod, "WinHttpWebSocketClose" );
|
||||
pWinHttpWebSocketCompleteUpgrade = (void *)GetProcAddress( mod, "WinHttpWebSocketCompleteUpgrade" );
|
||||
pWinHttpWebSocketQueryCloseStatus = (void *)GetProcAddress( mod, "WinHttpWebSocketQueryCloseStatus" );
|
||||
pWinHttpWebSocketReceive = (void *)GetProcAddress( mod, "WinHttpWebSocketReceive" );
|
||||
pWinHttpWebSocketSend = (void *)GetProcAddress( mod, "WinHttpWebSocketSend" );
|
||||
pWinHttpWebSocketShutdown = (void *)GetProcAddress( mod, "WinHttpWebSocketShutdown" );
|
||||
|
||||
test_connection_cache();
|
||||
test_redirect();
|
||||
test_async();
|
||||
test_websocket();
|
||||
|
||||
si.event = CreateEventW( NULL, 0, 0, NULL );
|
||||
si.port = 7533;
|
||||
|
|
Loading…
Reference in New Issue