]> git.ozlabs.org Git - ccan/commitdiff
net: make tests more robust.
authorRusty Russell <rusty@rustcorp.com.au>
Thu, 7 Feb 2013 00:42:27 +0000 (11:12 +1030)
committerRusty Russell <rusty@rustcorp.com.au>
Thu, 7 Feb 2013 00:45:50 +0000 (11:15 +1030)
Andreas Schlick reports failure on systems without IPv6 support (in particular
ones with no IPv6 addresses for localhost).  We should be more robust in
these cases, and also where IPv4 support is missing.

Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>
ccan/net/test/run.c

index bff1b6a79e47a47ec0ba994f4a83f980a2d91d27..bdd5f1de8e49d82d3cb46460098e60cc3955e30a 100644 (file)
@@ -6,7 +6,7 @@
 #include <stdio.h>
 #include <err.h>
 
 #include <stdio.h>
 #include <err.h>
 
-static unsigned int server(int protocol, int type)
+static int server(int protocol, int type)
 {
        int sock;
        union {
 {
        int sock;
        union {
@@ -17,9 +17,12 @@ static unsigned int server(int protocol, int type)
        socklen_t addlen = sizeof(addr);
 
        sock = socket(protocol, type, 0);
        socklen_t addlen = sizeof(addr);
 
        sock = socket(protocol, type, 0);
+       if (sock < 0)
+               return -1;
 
        /* Bind to free port. */
 
        /* Bind to free port. */
-       listen(sock, 0);
+       if (listen(sock, 0) != 0)
+               return -1;
 
        /* Figure out what port it gave us. */
        getsockname(sock, &addr.addr, &addlen);
 
        /* Figure out what port it gave us. */
        getsockname(sock, &addr.addr, &addlen);
@@ -43,10 +46,8 @@ static unsigned int server(int protocol, int type)
                     ? addr.ipv4.sin_port : addr.ipv6.sin6_port);
 }
 
                     ? addr.ipv4.sin_port : addr.ipv6.sin6_port);
 }
 
-static bool we_faked_double = false;
-
-/* Get a localhost on ipv4 and IPv6.  Fake it if we have to. */
-static struct addrinfo* double_addr_lookup(char* buf)
+/* Get a localhost on ipv4 and IPv6.  Fake it if we can. */
+static struct addrinfo* double_addr_lookup(char* buf, bool *fake_double)
 {
        struct addrinfo *addr, *addr2;
 
 {
        struct addrinfo *addr, *addr2;
 
@@ -57,9 +58,8 @@ static struct addrinfo* double_addr_lookup(char* buf)
        /* If we only got one, we need to fake up the other one. */
        if (addr->ai_next) {
                addr2 = addr->ai_next;
        /* If we only got one, we need to fake up the other one. */
        if (addr->ai_next) {
                addr2 = addr->ai_next;
+               *fake_double = false;
        } else {
        } else {
-               we_faked_double = true;
-
                /* OK, IPv4 only? */
                if (addr->ai_family == AF_INET) {
                        /* These are the names I found on my Ubuntu system. */
                /* OK, IPv4 only? */
                if (addr->ai_family == AF_INET) {
                        /* These are the names I found on my Ubuntu system. */
@@ -77,8 +77,14 @@ static struct addrinfo* double_addr_lookup(char* buf)
                        /* IPv6 only?  This is a guess... */
                        addr2 = net_client_lookup("ip4-localhost", buf,
                                                  AF_UNSPEC, SOCK_STREAM);
                        /* IPv6 only?  This is a guess... */
                        addr2 = net_client_lookup("ip4-localhost", buf,
                                                  AF_UNSPEC, SOCK_STREAM);
-               if (!addr2)
-                       return NULL;
+
+               /* Perhaps no support on this system?  Go ahead with one. */
+               if (!addr2) {
+                       *fake_double = false;
+                       return addr;
+               }
+
+               *fake_double = true;
                addr->ai_next = addr2;
        }
 
                addr->ai_next = addr2;
        }
 
@@ -93,16 +99,13 @@ static struct addrinfo* double_addr_lookup(char* buf)
        return NULL;
 }
 
        return NULL;
 }
 
-static void double_addr_free(struct addrinfo* addr)
+static void double_addr_free(struct addrinfo* addr, bool fake_double)
 {
 {
-       struct addrinfo *addr2;
-       if (we_faked_double) {
-               addr2 = addr->ai_next;
+       if (fake_double) {
+               freeaddrinfo(addr->ai_next);
                addr->ai_next = NULL;
        }
        freeaddrinfo(addr);
                addr->ai_next = NULL;
        }
        freeaddrinfo(addr);
-       if (we_faked_double)
-               freeaddrinfo(addr2);
 }
 
 int main(void)
 }
 
 int main(void)
@@ -112,45 +115,65 @@ int main(void)
        struct sockaddr saddr;
        socklen_t slen;
        char buf[20];
        struct sockaddr saddr;
        socklen_t slen;
        char buf[20];
-       unsigned int port;
+       int port;
+       bool fake_double;
 
        plan_tests(14);
 
        plan_tests(14);
+
        port = server(AF_INET, SOCK_STREAM);
        port = server(AF_INET, SOCK_STREAM);
-       sprintf(buf, "%u", port);
-
-       addr = double_addr_lookup(buf);
-       ok1(addr);
-       fd = net_connect(addr);
-       ok1(fd >= 0);
-
-       slen = sizeof(saddr);
-       ok1(getsockname(fd, &saddr, &slen) == 0);
-       diag("family = %d", saddr.sa_family);
-       ok1(saddr.sa_family == AF_INET);
-       status = read(fd, buf, sizeof(buf));
-       ok(status == strlen("Yay!"),
-          "Read returned %i (%s)", status, strerror(errno));
-       ok1(strncmp(buf, "Yay!", strlen("Yay!")) == 0);
-       close(fd);
-       double_addr_free(addr);
+       if (port == -1) {
+               /* No IPv4 support?  Maybe one day this will happen! */
+               if (errno == EAFNOSUPPORT)
+                       skip(6, "No IPv4 socket support");
+               else
+                       fail("Could not create IPv4 listening socket: %s",
+                            strerror(errno));
+       } else {
+               sprintf(buf, "%u", port);
+
+               addr = double_addr_lookup(buf, &fake_double);
+               ok1(addr);
+               fd = net_connect(addr);
+               ok1(fd >= 0);
+
+               slen = sizeof(saddr);
+               ok1(getsockname(fd, &saddr, &slen) == 0);
+               diag("family = %d", saddr.sa_family);
+               ok1(saddr.sa_family == AF_INET);
+               status = read(fd, buf, sizeof(buf));
+               ok(status == strlen("Yay!"),
+                  "Read returned %i (%s)", status, strerror(errno));
+               ok1(strncmp(buf, "Yay!", strlen("Yay!")) == 0);
+               close(fd);
+               double_addr_free(addr, fake_double);
+       }
 
        port = server(AF_INET6, SOCK_STREAM);
 
        port = server(AF_INET6, SOCK_STREAM);
-       sprintf(buf, "%u", port);
-
-       addr = double_addr_lookup(buf);
-       ok1(addr);
-       fd = net_connect(addr);
-       ok1(fd >= 0);
-
-       slen = sizeof(saddr);
-       ok1(getsockname(fd, &saddr, &slen) == 0);
-       ok1(saddr.sa_family == AF_INET6);
-       status = read(fd, buf, sizeof(buf));
-       ok(status == strlen("Yay!"),
-          "Read returned %i (%s)", status, strerror(errno));
-       ok1(strncmp(buf, "Yay!", strlen("Yay!")) == 0);
-       close(fd);
-       double_addr_free(addr);
+       if (port == -1) {
+               /* No IPv6 support? */
+               if (errno == EAFNOSUPPORT)
+                       skip(6, "No IPv6 socket support");
+               else
+                       fail("Could not create IPv6 listening socket: %s",
+                            strerror(errno));
+       } else {
+               sprintf(buf, "%u", port);
+
+               addr = double_addr_lookup(buf, &fake_double);
+               ok1(addr);
+               fd = net_connect(addr);
+               ok1(fd >= 0);
+
+               slen = sizeof(saddr);
+               ok1(getsockname(fd, &saddr, &slen) == 0);
+               ok1(saddr.sa_family == AF_INET6);
+               status = read(fd, buf, sizeof(buf));
+               ok(status == strlen("Yay!"),
+                  "Read returned %i (%s)", status, strerror(errno));
+               ok1(strncmp(buf, "Yay!", strlen("Yay!")) == 0);
+               close(fd);
+               double_addr_free(addr, fake_double);
+       }
 
        wait(&status);
        ok1(WIFEXITED(status));
 
        wait(&status);
        ok1(WIFEXITED(status));