winsock conformance test - added tests for sendto, recvfrom, and getservbyname

Thomas Kho thomaskho at gmail.com
Sat Mar 19 19:57:40 CST 2005


Hi,

We're working to add conformance tests to winsock, and we've currently
added tests for sendto, recvfrom, and getservbyname.

We chose these previously untested functions to test for the following
reasons:
- UDP is often used and was not previously tested
- getservbyname uses the same critical section code as the other
database functions; we thought it would be useful to stress tests this.

We ran gcov to see how much of dlls/winsock/socket.c we tested, and found:

Before: 41.16% of file dlls/winsock/socket.c
After: 46.38% of file dlls/winsock/socket.c

http://hkn.icsl.ucla.edu/~tom/socket_c_2.gcov.txt

Thanks for your help,

Thomas Kho


Files available at:
http://www.geekymedia.com/viewcvs/cgi/viewcvs.cgi/wine4/wine/dlls/winsock/tests/

Changelog:
  * dlls/winsock/tests/sock.c
    added tests for sendto, recvfrom, and getservbyname

-------------- next part --------------
# Signed-off-by: Thomas Kho <tkho at ucla.edu>
# 
--- wine_cvs/dlls/winsock/tests/sock.c	2005-03-15 07:49:01.000000000 -0800
+++ wine_build/dlls/winsock/tests/sock.c	2005-03-15 15:14:52.000000000 -0800
@@ -37,6 +37,14 @@
 #define TEST_TIMEOUT 30    /* seconds to wait before killing child threads
                               after server initialization, if something hangs */
 
+#define NUM_UDP_PEERS 3    /* Number of UDP sockets to create and test > 1 */
+
+#define NUM_THREADS 3      /* Number of threads to run getservbyname */
+#define NUM_QUERIES 250    /* Number of getservbyname queries per thread */
+
+#define SERVERIP "127.0.0.1"   /* IP to bind to */
+#define SERVERPORT 9374        /* Port number to bind to */
+
 #define wsa_ok(op, cond, msg) \
    do { \
         int tmp, err = 0; \
@@ -862,8 +870,8 @@
 #define STD_STREAM_SOCKET \
             SOCK_STREAM, \
             0, \
-            "127.0.0.1", \
-            9374
+            SERVERIP, \
+            SERVERPORT
 
 static test_setup tests [NUM_TESTS] =
 {
@@ -932,6 +940,105 @@
     }
 };
 
+static void test_UDP()
+{
+    /* This function tests UDP sendto() and recvfrom(). UDP is unreliable, so it is
+       possible that this test fails due to dropped packets. */
+
+    /* peer 0 receives data from all other peers */
+    struct sock_info peer[NUM_UDP_PEERS];
+    char buf[16];
+    int ss, i, n_recv, n_sent;
+
+    for ( i = NUM_UDP_PEERS - 1; i >= 0; i-- ) {
+        ok ( ( peer[i].s = socket ( AF_INET, SOCK_DGRAM, 0 ) ) != INVALID_SOCKET, "UDP: socket failed\n" );
+
+        peer[i].addr.sin_family         = AF_INET;
+        peer[i].addr.sin_addr.s_addr    = inet_addr ( SERVERIP );
+
+        if ( i == 0 ) {
+            peer[i].addr.sin_port       = htons ( SERVERPORT );
+        } else {
+            peer[i].addr.sin_port       = htons ( 0 );
+        }
+
+        do_bind ( peer[i].s, (struct sockaddr *) &peer[i].addr, sizeof( peer[i].addr ) );
+
+        /* test getsockname() to get peer's port */
+        ss = sizeof ( peer[i].addr );
+        ok ( getsockname ( peer[i].s, (struct sockaddr *) &peer[i].addr, &ss ) != SOCKET_ERROR, "UDP: could not getsockname()\n" );
+        ok ( peer[i].addr.sin_port != htons ( 0 ), "UDP: bind() did not associate port\n" );
+    }
+
+    /* test getsockname() */
+    ok ( peer[0].addr.sin_port == htons ( SERVERPORT ), "UDP: getsockname returned incorrect peer port\n" );
+
+    for ( i = 1; i < NUM_UDP_PEERS; i++ ) {
+        /* send client's ip */
+        memcpy( buf, &peer[i].addr.sin_port, sizeof(peer[i].addr.sin_port) );
+        n_sent = sendto ( peer[i].s, buf, sizeof(buf), 0, (struct sockaddr*) &peer[0].addr, sizeof(peer[0].addr) );
+        ok ( n_sent == sizeof(buf), "UDP: sendto() sent wrong amount of data or socket error: %d\n", n_sent );
+    }
+
+    for ( i = 1; i < NUM_UDP_PEERS; i++ ) {
+        n_recv = recvfrom ( peer[0].s, buf, sizeof(buf), 0,(struct sockaddr *) &peer[0].peer, &ss );
+        ok ( n_recv == sizeof(buf), "UDP: recvfrom() received wrong amount of data or socket error: %d\n", n_recv );
+        ok ( memcmp ( &peer[0].peer.sin_port, buf, sizeof(peer[0].addr.sin_port) ) == 0, "UDP: port numbers do not match\n" );
+    }
+}
+
+static void WINAPI do_getservbyname( HANDLE *starttest )
+{
+    struct {
+        char *name;
+        char *proto;
+        int port;
+    } serv[2] = { {"domain", "udp", 53}, {"telnet", "tcp", 23} };
+
+    int i, j;
+    struct servent *pserv[2];
+
+    ok ( WaitForSingleObject ( *starttest, TEST_TIMEOUT * 1000 ) != WAIT_TIMEOUT, "test_getservbyname: timeout waiting for start signal\n");
+
+    // ensure that necessary buffer resizes are completed
+    for ( j = 0; j < 2; j++) {
+        pserv[j] = getservbyname ( serv[j].name, serv[j].proto );
+    }
+
+    for ( i = 0; i < NUM_QUERIES / 2; i++ ) {
+        for ( j = 0; j < 2; j++ ) {
+            pserv[j] = getservbyname ( serv[j].name, serv[j].proto );
+            ok ( pserv[j] != NULL, "getservbyname could not retreive information for %s: %d\n", serv[j].name, WSAGetLastError() );
+            ok ( pserv[j]->s_port == htons(serv[j].port), "getservbyname returned the wrong port for %s: %d\n", serv[j].name, ntohs(pserv[j]->s_port) );
+            ok ( !strcmp ( pserv[j]->s_proto, serv[j].proto ), "getservbyname returned the wrong protocol for %s: %s\n", serv[j].name, pserv[j]->s_proto );
+            ok ( !strcmp ( pserv[j]->s_name, serv[j].name ), "getservbyname returned the wrong name for %s: %s\n", serv[j].name, pserv[j]->s_name );
+        }
+
+        ok ( pserv[0] == pserv[1], "getservbyname: winsock resized servent buffer when not necessary\n" );
+    }
+}
+
+static void test_getservbyname()
+{
+    int i;
+    HANDLE starttest, thread[NUM_THREADS];
+    DWORD thread_id[NUM_THREADS];
+
+    starttest = CreateEvent ( NULL, 1, 0, "test_getservbyname_starttest" );
+
+    /* create threads */
+    for ( i = 0; i < NUM_THREADS; i++ ) {
+        thread[i] = CreateThread ( NULL, 0, (LPTHREAD_START_ROUTINE) &do_getservbyname, &starttest, 0, &thread_id[i] );
+    }
+
+    /* signal threads to start */
+    SetEvent ( starttest );
+
+    for ( i = 0; i < NUM_THREADS; i++) {
+        WaitForSingleObject ( thread[i], TEST_TIMEOUT * 1000 );
+    }
+}
+
 static void test_WSAAddressToStringA()
 {
     INT ret;
@@ -1191,6 +1298,10 @@
         trace ( " **** TEST %d COMPLETE **** \n", i );
     }
 
+    test_UDP();
+
+    test_getservbyname();
+
     test_WSAAddressToStringA();
     test_WSAAddressToStringW();
 



More information about the wine-patches mailing list