From: Hans Leidekker Subject: [7/8] webservices/tests: Add tests for WsSendMessage. Message-Id: <1475059086-6011-7-git-send-email-hans@codeweavers.com> Date: Wed, 28 Sep 2016 12:38:05 +0200 Signed-off-by: Hans Leidekker --- dlls/webservices/tests/Makefile.in | 2 +- dlls/webservices/tests/proxy.c | 221 ++++++++++++++++++++++++++++++++++++- 2 files changed, 220 insertions(+), 3 deletions(-) diff --git a/dlls/webservices/tests/Makefile.in b/dlls/webservices/tests/Makefile.in index afff870..e63952c 100644 --- a/dlls/webservices/tests/Makefile.in +++ b/dlls/webservices/tests/Makefile.in @@ -1,5 +1,5 @@ TESTDLL = webservices.dll -IMPORTS = webservices +IMPORTS = webservices user32 ws2_32 C_SRCS = \ channel.c \ diff --git a/dlls/webservices/tests/proxy.c b/dlls/webservices/tests/proxy.c index ba0ecd3..ef64faf 100644 --- a/dlls/webservices/tests/proxy.c +++ b/dlls/webservices/tests/proxy.c @@ -18,6 +18,7 @@ #include #include "windows.h" +#include "winsock2.h" #include "webservices.h" #include "wine/test.h" @@ -29,12 +30,12 @@ static void test_WsCreateServiceProxy(void) ULONG size, value; hr = WsCreateServiceProxy( WS_CHANNEL_TYPE_REQUEST, WS_HTTP_CHANNEL_BINDING, NULL, NULL, - 0, NULL, 0, NULL, NULL ) ; + 0, NULL, 0, NULL, NULL ); ok( hr == E_INVALIDARG, "got %08x\n", hr ); proxy = NULL; hr = WsCreateServiceProxy( WS_CHANNEL_TYPE_REQUEST, WS_HTTP_CHANNEL_BINDING, NULL, NULL, - 0, NULL, 0, &proxy, NULL ) ; + 0, NULL, 0, &proxy, NULL ); ok( hr == S_OK, "got %08x\n", hr ); ok( proxy != NULL, "proxy not set\n" ); @@ -104,9 +105,225 @@ static void test_WsOpenServiceProxy(void) WsFreeServiceProxy( proxy ); } +static HRESULT create_channel( int port, WS_CHANNEL **ret ) +{ + static const WCHAR fmt[] = + {'h','t','t','p',':','/','/','1','2','7','.','0','.','0','.','1',':','%','u',0}; + WS_CHANNEL_PROPERTY prop[2]; + WS_ENVELOPE_VERSION env_version = WS_ENVELOPE_VERSION_SOAP_1_1; + WS_ADDRESSING_VERSION addr_version = WS_ADDRESSING_VERSION_TRANSPORT; + WS_CHANNEL *channel; + WS_ENDPOINT_ADDRESS addr; + WCHAR buf[64]; + HRESULT hr; + + prop[0].id = WS_CHANNEL_PROPERTY_ENVELOPE_VERSION; + prop[0].value = &env_version; + prop[0].valueSize = sizeof(env_version); + + prop[1].id = WS_CHANNEL_PROPERTY_ADDRESSING_VERSION; + prop[1].value = &addr_version; + prop[1].valueSize = sizeof(addr_version); + + *ret = NULL; + hr = WsCreateChannel( WS_CHANNEL_TYPE_REQUEST, WS_HTTP_CHANNEL_BINDING, prop, 2, NULL, &channel, NULL ); + if (hr != S_OK) return hr; + + addr.url.length = wsprintfW( buf, fmt, port ); + addr.url.chars = buf; + addr.headers = NULL; + addr.extensions = NULL; + addr.identity = NULL; + hr = WsOpenChannel( channel, &addr, NULL, NULL ); + if (hr == S_OK) *ret = channel; + else WsFreeChannel( channel ); + return hr; +} + +static const char req_test1[] = + "" + "-1" + ""; + +static const char resp_test1[] = + "" + "-2" + ""; + +static void test_WsSendMessage( int port, WS_XML_STRING *action ) +{ + WS_XML_STRING req = {9, (BYTE *)"req_test1"}, ns = {2, (BYTE *)"ns"}; + WS_CHANNEL *channel; + WS_MESSAGE *msg; + WS_ELEMENT_DESCRIPTION body; + WS_MESSAGE_DESCRIPTION desc; + INT32 val = -1; + HRESULT hr; + + hr = create_channel( port, &channel ); + ok( hr == S_OK, "got %08x\n", hr ); + + hr = WsCreateMessageForChannel( channel, NULL, 0, &msg, NULL ); + ok( hr == S_OK, "got %08x\n", hr ); + + body.elementLocalName = &req; + body.elementNs = &ns; + body.type = WS_INT32_TYPE; + body.typeDescription = NULL; + desc.action = action; + desc.bodyElementDescription = &body; + hr = WsSendMessage( NULL, msg, &desc, WS_WRITE_REQUIRED_VALUE, &val, sizeof(val), NULL, NULL ); + ok( hr == E_INVALIDARG, "got %08x\n", hr ); + + hr = WsSendMessage( channel, NULL, &desc, WS_WRITE_REQUIRED_VALUE, &val, sizeof(val), NULL, NULL ); + ok( hr == E_INVALIDARG, "got %08x\n", hr ); + + hr = WsSendMessage( channel, msg, NULL, WS_WRITE_REQUIRED_VALUE, &val, sizeof(val), NULL, NULL ); + ok( hr == E_INVALIDARG, "got %08x\n", hr ); + + hr = WsSendMessage( channel, msg, &desc, WS_WRITE_REQUIRED_VALUE, &val, sizeof(val), NULL, NULL ); + ok( hr == S_OK, "got %08x\n", hr ); + + hr = WsCloseChannel( channel, NULL, NULL ); + ok( hr == S_OK, "got %08x\n", hr ); + + WsFreeChannel( channel ); + WsFreeMessage( msg ); +} + +static const struct +{ + const char *req_action; + const char *req_data; + unsigned int req_len; + const char *resp_action; + const char *resp_data; + unsigned int resp_len; +} +tests[] = +{ + { "req_test1", req_test1, sizeof(req_test1)-1, "resp_test1", resp_test1, sizeof(resp_test1)-1 }, +}; + +static void send_response( int c, const char *action, const char *data, unsigned int len ) +{ + static const char headers[] = + "HTTP/1.1 200 OK\r\nContent-Type: text/xml; charset=utf-8\r\nConnection: close\r\n"; + static const char fmt[] = + "SOAPAction: \"%s\"\r\nContent-Length: %u\r\n\r\n"; + char buf[128]; + + send( c, headers, sizeof(headers) - 1, 0 ); + sprintf( buf, fmt, action, len ); + send( c, buf, strlen(buf), 0 ); + send( c, data, len, 0 ); +} + +struct server_info +{ + HANDLE event; + int port; +}; + +static DWORD CALLBACK server_proc( void *arg ) +{ + struct server_info *info = arg; + int len, res, c = -1, i, j, on = 1, quit; + WSADATA wsa; + SOCKET s; + struct sockaddr_in sa; + char buf[1024]; + const char *p; + + WSAStartup( MAKEWORD(1,1), &wsa ); + if ((s = socket( AF_INET, SOCK_STREAM, 0 )) == INVALID_SOCKET) return 1; + setsockopt( s, SOL_SOCKET, SO_REUSEADDR, (char *)&on, sizeof(on) ); + + memset( &sa, 0, sizeof(sa) ); + sa.sin_family = AF_INET; + sa.sin_port = htons( info->port ); + sa.sin_addr.S_un.S_addr = inet_addr( "127.0.0.1" ); + if (bind( s, (struct sockaddr *)&sa, sizeof(sa) ) < 0) return 1; + + listen( s, 0 ); + SetEvent( info->event ); + for (;;) + { + c = accept( s, NULL, NULL ); + + buf[0] = 0; + for (i = 0; i < sizeof(buf) - 1; i++) + { + if ((res = recv( c, &buf[i], 1, 0 )) != 1) break; + if (i < 4) continue; + if (buf[i - 2] == '\n' && buf[i] == '\n' && buf[i - 3] == '\r' && buf[i - 1] == '\r') + break; + } + buf[i] = 0; + quit = strstr( buf, "SOAPAction: \"quit\"" ) != NULL; + + len = 0; + if ((p = strstr( buf, "Content-Length: " ))) + { + p += strlen( "Content-Length: " ); + while (isdigit( *p )) + { + len *= 10; + len += *p++ - '0'; + } + } + for (i = 0; i < len; i++) + { + if ((res = recv( c, &buf[i], 1, 0 )) != 1) break; + } + buf[i] = 0; + + for (j = 0; j < sizeof(tests)/sizeof(tests[0]); j++) + { + if (strstr( buf, tests[j].req_action )) + { + if (tests[j].req_data) + { + int data_len = strlen( buf ); + ok( tests[j].req_len == data_len, "%u: unexpected data length %u %u\n", + j, data_len, tests[j].req_len ); + if (tests[j].req_len == data_len) + ok( !memcmp( tests[j].req_data, buf, tests[j].req_len ), "%u: unexpected data\n", j ); + } + send_response( c, tests[j].resp_action, tests[j].resp_data, tests[j].resp_len ); + } + } + + shutdown( c, 2 ); + closesocket( c ); + if (quit) break; + } + + return 0; +} + START_TEST(proxy) { + WS_XML_STRING test1 = {9, (BYTE *)"req_test1"}; + WS_XML_STRING quit = {4, (BYTE *)"quit"}; + struct server_info info; + HANDLE thread; + DWORD ret; + test_WsCreateServiceProxy(); test_WsCreateServiceProxyFromTemplate(); test_WsOpenServiceProxy(); + + info.port = 7533; + info.event = CreateEventW( NULL, 0, 0, NULL ); + thread = CreateThread( NULL, 0, server_proc, &info, 0, NULL ); + ok( thread != NULL, "failed to create server thread %u\n", GetLastError() ); + + ret = WaitForSingleObject( info.event, 3000 ); + ok(ret == WAIT_OBJECT_0, "failed to start test server %u\n", GetLastError()); + if (ret != WAIT_OBJECT_0) return; + + test_WsSendMessage( info.port, &test1 ); + test_WsSendMessage( info.port, &quit ); + WaitForSingleObject( thread, 3000 ); } -- 2.1.4