Extend test suite to test AF_UNIX functionality
authorWouter Verhelst <w@uter.be>
Mon, 2 Mar 2015 17:52:45 +0000 (18:52 +0100)
committerWouter Verhelst <w@uter.be>
Mon, 2 Mar 2015 17:53:36 +0000 (18:53 +0100)
tests/run/Makefile.am
tests/run/nbd-tester-client.c
tests/run/simple_test

index 3487bd9..2a54d4f 100644 (file)
@@ -1,5 +1,5 @@
 TESTS_ENVIRONMENT=$(srcdir)/simple_test
-TESTS = cmd cfg1 cfgmulti cfgnew cfgsize write flush integrity dirconfig list rowrite tree rotree #integrityhuge
+TESTS = cmd cfg1 cfgmulti cfgnew cfgsize write flush integrity dirconfig list rowrite tree rotree unix #integrityhuge
 check_PROGRAMS = nbd-tester-client
 nbd_tester_client_SOURCES = nbd-tester-client.c $(top_srcdir)/cliserv.h $(top_srcdir)/netdb-compat.h $(top_srcdir)/cliserv.c
 nbd_tester_client_CFLAGS = @CFLAGS@ @GLIB_CFLAGS@
@@ -20,3 +20,4 @@ list:
 rowrite:
 tree:
 rotree:
+unix:
index 14db32d..c07f92d 100644 (file)
@@ -27,6 +27,7 @@
 #include <string.h>
 #include <sys/time.h>
 #include <sys/types.h>
+#include <sys/un.h>
 #include <sys/socket.h>
 #include <sys/stat.h>
 #include <sys/mman.h>
@@ -336,81 +337,123 @@ static inline int write_all(int f, void *buf, size_t len) {
 #define WRITE_ALL_ERRCHK(f, buf, len, whereto, errmsg...) if((write_all(f, buf, len))<=0) { snprintf(errstr, errstr_len, ##errmsg); goto whereto; }
 #define WRITE_ALL_ERR_RT(f, buf, len, whereto, rval, errmsg...) if((write_all(f, buf, len))<=0) { snprintf(errstr, errstr_len, ##errmsg); retval = rval; goto whereto; }
 
-int setup_connection(gchar *hostname, int port, gchar* name, CONNECTION_TYPE ctype, int* serverflags) {
-       int sock;
-       struct hostent *host;
-       struct sockaddr_in addr;
+int setup_connection_common(int sock, char* name, CONNECTION_TYPE ctype, int* serverflags) {
        char buf[256];
-       uint64_t mymagic = (name ? opts_magic : cliserv_magic);
        u64 tmp64;
+       uint64_t mymagic = (name ? opts_magic : cliserv_magic);
        uint32_t tmp32 = 0;
 
-       sock=0;
-       if(ctype<CONNECTION_TYPE_CONNECT)
-               goto end;
-       if((sock=socket(PF_INET, SOCK_STREAM, IPPROTO_TCP))<0) {
-               strncpy(errstr, strerror(errno), errstr_len);
-               goto err;
-       }
-       setmysockopt(sock);
-       if(!(host=gethostbyname(hostname))) {
-               strncpy(errstr, hstrerror(h_errno), errstr_len);
-               goto err_open;
-       }
-       addr.sin_family=AF_INET;
-       addr.sin_port=htons(port);
-       addr.sin_addr.s_addr=*((int *) host->h_addr);
-       if((connect(sock, (struct sockaddr *)&addr, sizeof(addr))<0)) {
-               strncpy(errstr, strerror(errno), errstr_len);
-               goto err_open;
-       }
        if(ctype<CONNECTION_TYPE_INIT_PASSWD)
                goto end;
-       READ_ALL_ERRCHK(sock, buf, strlen(INIT_PASSWD), err_open, "Could not read INIT_PASSWD: %s", strerror(errno));
+       READ_ALL_ERRCHK(sock, buf, strlen(INIT_PASSWD), err, "Could not read INIT_PASSWD: %s", strerror(errno));
        if(strlen(buf)==0) {
                snprintf(errstr, errstr_len, "Server closed connection");
-               goto err_open;
+               goto err;
        }
        if(strncmp(buf, INIT_PASSWD, strlen(INIT_PASSWD))) {
                snprintf(errstr, errstr_len, "INIT_PASSWD does not match");
-               goto err_open;
+               goto err;
        }
        if(ctype<CONNECTION_TYPE_CLISERV)
                goto end;
-       READ_ALL_ERRCHK(sock, &tmp64, sizeof(tmp64), err_open, "Could not read cliserv_magic: %s", strerror(errno));
+       READ_ALL_ERRCHK(sock, &tmp64, sizeof(tmp64), err, "Could not read cliserv_magic: %s", strerror(errno));
        tmp64=ntohll(tmp64);
        if(tmp64 != mymagic) {
                strncpy(errstr, "mymagic does not match", errstr_len);
-               goto err_open;
+               goto err;
        }
        if(ctype<CONNECTION_TYPE_FULL)
                goto end;
        if(!name) {
-               READ_ALL_ERRCHK(sock, &size, sizeof(size), err_open, "Could not read size: %s", strerror(errno));
+               READ_ALL_ERRCHK(sock, &size, sizeof(size), err, "Could not read size: %s", strerror(errno));
                size=ntohll(size);
-               READ_ALL_ERRCHK(sock, buf, 128, err_open, "Could not read data: %s", strerror(errno));
+               READ_ALL_ERRCHK(sock, buf, 128, err, "Could not read data: %s", strerror(errno));
                goto end;
        }
        /* flags */
-       READ_ALL_ERRCHK(sock, buf, sizeof(uint16_t), err_open, "Could not read reserved field: %s", strerror(errno));
+       READ_ALL_ERRCHK(sock, buf, sizeof(uint16_t), err, "Could not read reserved field: %s", strerror(errno));
        /* reserved field */
-       WRITE_ALL_ERRCHK(sock, &tmp32, sizeof(tmp32), err_open, "Could not write reserved field: %s", strerror(errno));
+       WRITE_ALL_ERRCHK(sock, &tmp32, sizeof(tmp32), err, "Could not write reserved field: %s", strerror(errno));
        /* magic */
        tmp64 = htonll(opts_magic);
-       WRITE_ALL_ERRCHK(sock, &tmp64, sizeof(tmp64), err_open, "Could not write magic: %s", strerror(errno));
+       WRITE_ALL_ERRCHK(sock, &tmp64, sizeof(tmp64), err, "Could not write magic: %s", strerror(errno));
        /* name */
        tmp32 = htonl(NBD_OPT_EXPORT_NAME);
-       WRITE_ALL_ERRCHK(sock, &tmp32, sizeof(tmp32), err_open, "Could not write option: %s", strerror(errno));
+       WRITE_ALL_ERRCHK(sock, &tmp32, sizeof(tmp32), err, "Could not write option: %s", strerror(errno));
        tmp32 = htonl((uint32_t)strlen(name));
-       WRITE_ALL_ERRCHK(sock, &tmp32, sizeof(tmp32), err_open, "Could not write name length: %s", strerror(errno));
-       WRITE_ALL_ERRCHK(sock, name, strlen(name), err_open, "Could not write name:: %s", strerror(errno));
-       READ_ALL_ERRCHK(sock, &size, sizeof(size), err_open, "Could not read size: %s", strerror(errno));
+       WRITE_ALL_ERRCHK(sock, &tmp32, sizeof(tmp32), err, "Could not write name length: %s", strerror(errno));
+       WRITE_ALL_ERRCHK(sock, name, strlen(name), err, "Could not write name:: %s", strerror(errno));
+       READ_ALL_ERRCHK(sock, &size, sizeof(size), err, "Could not read size: %s", strerror(errno));
        size = ntohll(size);
        uint16_t flags;
-       READ_ALL_ERRCHK(sock, &flags, sizeof(uint16_t), err_open, "Could not read flags: %s", strerror(errno));
+       READ_ALL_ERRCHK(sock, &flags, sizeof(uint16_t), err, "Could not read flags: %s", strerror(errno));
        flags = ntohs(flags);
        *serverflags = flags;
-       READ_ALL_ERRCHK(sock, buf, 124, err_open, "Could not read reserved zeroes: %s", strerror(errno));
+       READ_ALL_ERRCHK(sock, buf, 124, err, "Could not read reserved zeroes: %s", strerror(errno));
+       goto end;
+err:
+       close(sock);
+       sock=-1;
+end:
+       return sock;
+}
+
+int setup_unix_connection(gchar* unixsock, gchar* name, CONNECTION_TYPE ctype, int* serverflags) {
+       struct sockaddr_un addr;
+       int sock;
+
+       sock = 0;
+       if(ctype<CONNECTION_TYPE_CONNECT) {
+               goto end;
+       }
+       if((sock=socket(AF_UNIX, SOCK_STREAM, 0))<0) {
+               strncpy(errstr, strerror(errno), errstr_len);
+               goto err;
+       }
+
+       setmysockopt(sock);
+       memset(&addr, 0, sizeof(struct sockaddr_un));
+       addr.sun_family = AF_UNIX;
+       strncpy(addr.sun_path, unixsock, 107);
+       if(connect(sock, (struct sockaddr*)&addr, sizeof(addr))<0) {
+               strncpy(errstr, strerror(errno), errstr_len);
+               goto err_open;
+       }
+       sock = setup_connection_common(sock, name, ctype, serverflags);
+       goto end;
+err_open:
+       close(sock);
+err:
+       sock=-1;
+end:
+       return sock;
+}
+
+int setup_inet_connection(gchar *hostname, int port, gchar* name, CONNECTION_TYPE ctype, int* serverflags) {
+       int sock;
+       struct hostent *host;
+       struct sockaddr_in addr;
+
+       sock=0;
+       if(ctype<CONNECTION_TYPE_CONNECT)
+               goto end;
+       if((sock=socket(PF_INET, SOCK_STREAM, IPPROTO_TCP))<0) {
+               strncpy(errstr, strerror(errno), errstr_len);
+               goto err;
+       }
+       setmysockopt(sock);
+       if(!(host=gethostbyname(hostname))) {
+               strncpy(errstr, hstrerror(h_errno), errstr_len);
+               goto err_open;
+       }
+       addr.sin_family=AF_INET;
+       addr.sin_port=htons(port);
+       addr.sin_addr.s_addr=*((int *) host->h_addr);
+       if((connect(sock, (struct sockaddr *)&addr, sizeof(addr))<0)) {
+               strncpy(errstr, strerror(errno), errstr_len);
+               goto err_open;
+       }
+       sock=setup_connection_common(sock, name, ctype, serverflags);
        goto end;
 err_open:
        close(sock);
@@ -420,6 +463,18 @@ end:
        return sock;
 }
 
+int setup_connection(gchar* hostname, gchar* unixsock, int port, gchar* name, CONNECTION_TYPE ctype, int* serverflags) {
+       int retval = 0;
+       if(hostname != NULL) {
+               return setup_inet_connection(hostname, port, name, ctype, serverflags);
+       } else if(unixsock != NULL) {
+               return setup_unix_connection(unixsock, name, ctype, serverflags);
+       } else {
+               g_error("need a hostname or a unix domain socket!");
+               return -1;
+       }
+}
+
 int close_connection(int sock, CLOSE_TYPE type) {
        struct nbd_request req;
        u64 counter=0;
@@ -474,7 +529,7 @@ end:
        return retval;
 }
 
-int oversize_test(gchar* hostname, int port, char* name, int sock,
+int oversize_test(gchar* hostname, gchar* unixsock, int port, char* name, int sock,
                  char sock_is_open, char close_sock, int testflags) {
        int retval=0;
        struct nbd_request req;
@@ -487,7 +542,7 @@ int oversize_test(gchar* hostname, int port, char* name, int sock,
 
        /* This should work */
        if(!sock_is_open) {
-               if((sock=setup_connection(hostname, port, name, CONNECTION_TYPE_FULL, &serverflags))<0) {
+               if((sock=setup_connection(hostname, unixsock, port, name, CONNECTION_TYPE_FULL, &serverflags))<0) {
                        g_warning("Could not open socket: %s", errstr);
                        retval=-1;
                        goto err;
@@ -543,7 +598,7 @@ int oversize_test(gchar* hostname, int port, char* name, int sock,
        return retval;
 }
 
-int throughput_test(gchar* hostname, int port, char* name, int sock,
+int throughput_test(gchar* hostname, gchar* unixsock, int port, char* name, int sock,
                    char sock_is_open, char close_sock, int testflags) {
        long long int i;
        char writebuf[1024];
@@ -568,7 +623,7 @@ int throughput_test(gchar* hostname, int port, char* name, int sock,
        memset (writebuf, 'X', 1024);
        size=0;
        if(!sock_is_open) {
-               if((sock=setup_connection(hostname, port, name, CONNECTION_TYPE_FULL, &serverflags))<0) {
+               if((sock=setup_connection(hostname, unixsock, port, name, CONNECTION_TYPE_FULL, &serverflags))<0) {
                        g_warning("Could not open socket: %s", errstr);
                        retval=-1;
                        goto err;
@@ -780,7 +835,7 @@ uint64_t getrandomhandle(GHashTable *phash) {
        return handle;
 }
 
-int integrity_test(gchar* hostname, int port, char* name, int sock,
+int integrity_test(gchar* hostname, gchar* unixsock, int port, char* name, int sock,
                   char sock_is_open, char close_sock, int testflags) {
        struct nbd_reply rep;
        fd_set rset;
@@ -812,7 +867,7 @@ int integrity_test(gchar* hostname, int port, char* name, int sock,
 
        size=0;
        if(!sock_is_open) {
-               if((sock=setup_connection(hostname, port, name, CONNECTION_TYPE_FULL, &serverflags))<0) {
+               if((sock=setup_connection(hostname, unixsock, port, name, CONNECTION_TYPE_FULL, &serverflags))<0) {
                        g_warning("Could not open socket: %s", errstr);
                        retval=-1;
                        goto err;
@@ -1281,10 +1336,10 @@ void handle_nonopt(char* opt, gchar** hostname, long int* p) {
        }
 }
 
-typedef int (*testfunc)(gchar*, int, char*, int, char, char, int);
+typedef int (*testfunc)(gchar*, gchar*, int, char*, int, char, char, int);
 
 int main(int argc, char**argv) {
-       gchar *hostname;
+       gchar *hostname=NULL, *unixsock=NULL;
        long int p = 0;
        char* name = NULL;
        int sock=0;
@@ -1302,10 +1357,11 @@ int main(int argc, char**argv) {
                g_message("%d: Not enough arguments", (int)getpid());
                g_message("%d: Usage: %s <hostname> <port>", (int)getpid(), argv[0]);
                g_message("%d: Or: %s <hostname> -N <exportname> [<port>]", (int)getpid(), argv[0]);
+               g_message("%d: Or: %s -u <unix socket> -N <exportname>", (int)getpid(), argv[0]);
                exit(EXIT_FAILURE);
        }
        logging(MY_NAME);
-       while((c=getopt(argc, argv, "-FN:t:owfil"))>=0) {
+       while((c=getopt(argc, argv, "-FN:t:owfilu:"))>=0) {
                switch(c) {
                        case 1:
                                handle_nonopt(optarg, &hostname, &p);
@@ -1337,6 +1393,9 @@ int main(int argc, char**argv) {
                        case 'i':
                                test=integrity_test;
                                break;
+                       case 'u':
+                               unixsock=g_strdup(optarg);
+                               break;
                }
        }
 
@@ -1344,7 +1403,7 @@ int main(int argc, char**argv) {
                handle_nonopt(argv[optind++], &hostname, &p);
        }
 
-       if(test(hostname, (int)p, name, sock, FALSE, TRUE, testflags)<0) {
+       if(test(hostname, unixsock, (int)p, name, sock, FALSE, TRUE, testflags)<0) {
                g_warning("Could not run test: %s", errstr);
                exit(EXIT_FAILURE);
        }
index 506a46f..3555656 100755 (executable)
@@ -278,6 +278,20 @@ EOF
                ./nbd-tester-client -N export1 -w -F localhost
                retval=$?
                ;;
+       */unix)
+               cat >${conffile} <<EOF
+[generic]
+       unixsock = ${tmpdir}/unix.sock
+       listenaddr = 127.0.0.1
+[export1]
+       exportname = ${tmpnam}
+EOF
+               ../../nbd-server -C ${conffile} -p ${pidfile} &
+               PID=$!
+               sleep 1
+               ./nbd-tester-client -N export1 -u ${tmpdir}/unix.sock
+               retval=$?
+               ;;
        *)
                echo "E: unknown test $1"
                exit 1