[7/8] webservices/tests: Add tests for WsSendMessage.

Hans Leidekker hans at codeweavers.com
Wed Sep 28 05:38:05 CDT 2016


Signed-off-by: Hans Leidekker <hans at codeweavers.com>
---
 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 <stdio.h>
 #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[] =
+    "<s:Envelope xmlns:s=\"http://schemas.xmlsoap.org/soap/envelope/\"><s:Body>"
+    "<req_test1 xmlns=\"ns\">-1</req_test1>"
+    "</s:Body></s:Envelope>";
+
+static const char resp_test1[] =
+    "<s:Envelope xmlns:s=\"http://schemas.xmlsoap.org/soap/envelope/\"><s:Body>"
+    "<resp_test1 xmlns=\"ns\">-2</resp_test1>"
+    "</s:Body></s:Envelope>";
+
+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




More information about the wine-patches mailing list