cURL / Mailing Lists / curl-library / Single Mail

curl-library

[PATCH 08/11] tests: add HTTP UNIX socket server testing support

From: Peter Wu <peter_at_lekensteyn.nl>
Date: Thu, 27 Nov 2014 23:59:23 +0100

The variable `$ipvnum` can now contain "unix" besides the integers 4
and 6 since the variable. Functions which receive this parameter
have their `$port` parameter renamed to `$port_or_path` to support a
path to the UNIX domain socket (as a "port" is only meaningful for TCP).

Signed-off-by: Peter Wu <peter_at_lekensteyn.nl>

---
 tests/FILEFORMAT    |  3 ++
 tests/README        |  3 ++
 tests/httpserver.pl | 15 ++++++++-
 tests/runtests.pl   | 97 ++++++++++++++++++++++++++++++++++++++++++++++-------
 tests/serverhelp.pm |  4 +--
 5 files changed, 106 insertions(+), 16 deletions(-)
diff --git a/tests/FILEFORMAT b/tests/FILEFORMAT
index a24007c..1637357 100644
--- a/tests/FILEFORMAT
+++ b/tests/FILEFORMAT
@@ -177,6 +177,7 @@ ftps
 http
 http-ipv6
 http-proxy
+http-unix
 https
 httptls+srp
 httptls+srp-ipv6
@@ -229,6 +230,7 @@ SSPI
 GSS-API
 Kerberos
 SPNEGO
+unix-sockets
 
 as well as each protocol that curl supports.  A protocol only needs to be
 specified if it is different from the server (useful when the server
@@ -331,6 +333,7 @@ Available substitute variables include:
 %HOSTIP       - IPv4 address of the host running this test
 %HTTP6PORT    - IPv6 port number of the HTTP server
 %HTTPPIPEPORT - Port number of the HTTP pipelining server
+%HTTPUNIXPATH - Path to the UNIX socket of the HTTP server
 %HTTPPORT     - Port number of the HTTP server
 %HTTPSPORT    - Port number of the HTTPS server
 %HTTPTLS6PORT - IPv6 port number of the HTTP TLS server
diff --git a/tests/README b/tests/README
index 1e5a879..7ef7f81 100644
--- a/tests/README
+++ b/tests/README
@@ -81,6 +81,9 @@ The cURL Test Suite
   machine, or just move the servers in case you have local services on any of
   those ports.
 
+  The HTTP server supports listening on a UNIX domain socket, the default
+  location is 'http.sock'.
+
  1.4 Run
 
   'make test'. This builds the test suite support code and invokes the
diff --git a/tests/httpserver.pl b/tests/httpserver.pl
index a38c3ce..1b8c3d2 100755
--- a/tests/httpserver.pl
+++ b/tests/httpserver.pl
@@ -36,6 +36,7 @@ use serverhelp qw(
 
 my $verbose = 0;     # set to 1 for debugging
 my $port = 8990;     # just a default
+my $unix_socket;     # location to place a listening UNIX socket
 my $ipvnum = 4;      # default IP version of http server
 my $idnum = 1;       # dafault http server instance number
 my $proto = 'http';  # protocol the http server speaks
@@ -74,6 +75,13 @@ while(@ARGV) {
     elsif($ARGV[0] eq '--ipv6') {
         $ipvnum = 6;
     }
+    elsif($ARGV[0] eq '--unix-socket') {
+        $ipvnum = 'unix';
+        if($ARGV[1]) {
+            $unix_socket = $ARGV[1];
+            shift @ARGV;
+        }
+    }
     elsif($ARGV[0] eq '--gopher') {
         $gopher = 1;
     }
@@ -117,7 +125,12 @@ if(!$logfile) {
 $flags .= "--pidfile \"$pidfile\" --logfile \"$logfile\" ";
 $flags .= "--gopher " if($gopher);
 $flags .= "--connect $connect " if($connect);
-$flags .= "--ipv$ipvnum --port $port --srcdir \"$srcdir\"";
+if($ipvnum eq 'unix') {
+    $flags .= "--unix-socket '$unix_socket' ";
+} else {
+    $flags .= "--ipv$ipvnum --port $port ";
+}
+$flags .= "--srcdir \"$srcdir\"";
 
 if($verbose) {
     print STDERR "RUN: server/sws $flags\n";
diff --git a/tests/runtests.pl b/tests/runtests.pl
index 46a78c4..b1bb558 100755
--- a/tests/runtests.pl
+++ b/tests/runtests.pl
@@ -141,6 +141,7 @@ my $HTTPTLSPORT;         # HTTP TLS (non-stunnel) server port
 my $HTTPTLS6PORT;        # HTTP TLS (non-stunnel) IPv6 server port
 my $HTTPPROXYPORT;       # HTTP proxy port, when using CONNECT
 my $HTTPPIPEPORT;        # HTTP pipelining port
+my $HTTPUNIXPATH;        # HTTP server UNIX domain socket path
 
 my $srcdir = $ENV{'srcdir'} || '.';
 my $CURL="../src/curl".exe_ext(); # what curl executable to run on the tests
@@ -202,10 +203,12 @@ my $ssl_version;    # set if libcurl is built with SSL support
 my $large_file;     # set if libcurl is built with large file support
 my $has_idn;        # set if libcurl is built with IDN support
 my $http_ipv6;      # set if HTTP server has IPv6 support
+my $http_unix;      # set if HTTP server has UNIX sockets support
 my $ftp_ipv6;       # set if FTP server has IPv6 support
 my $tftp_ipv6;      # set if TFTP server has IPv6 support
 my $gopher_ipv6;    # set if Gopher server has IPv6 support
 my $has_ipv6;       # set if libcurl is built with IPv6 support
+my $has_unix;       # set if libcurl is built with UNIX sockets support
 my $has_libz;       # set if libcurl is built with libz support
 my $has_getrlimit;  # set if system has getrlimit()
 my $has_ntlm;       # set if libcurl is built with NTLM support
@@ -377,6 +380,13 @@ sub init_serverpidfile_hash {
       }
     }
   }
+  for my $proto (('http', 'imap', 'pop3', 'smtp')) {
+    for my $ssl (('', 's')) {
+      my $serv = servername_id("$proto$ssl", "unix", 1);
+      my $pidf = server_pidfilename("$proto$ssl", "unix", 1);
+      $serverpidfile{$serv} = $pidf;
+    }
+  }
 }
 
 #######################################################################
@@ -662,11 +672,11 @@ sub stopserver {
     # All servers relative to the given one must be stopped also
     #
     my @killservers;
-    if($server =~ /^(ftp|http|imap|pop3|smtp|httppipe)s((\d*)(-ipv6|))$/) {
+    if($server =~ /^(ftp|http|imap|pop3|smtp|httppipe)s((\d*)(-ipv6|-unix|))$/) {
         # given a stunnel based ssl server, also kill non-ssl underlying one
         push @killservers, "${1}${2}";
     }
-    elsif($server =~ /^(ftp|http|imap|pop3|smtp|httppipe)((\d*)(-ipv6|))$/) {
+    elsif($server =~ /^(ftp|http|imap|pop3|smtp|httppipe)((\d*)(-ipv6|-unix|))$/) {
         # given a non-ssl server, also kill stunnel based ssl piggybacking one
         push @killservers, "${1}s${2}";
     }
@@ -712,10 +722,12 @@ sub stopserver {
 # assign requested address")
 #
 sub verifyhttp {
-    my ($proto, $ipvnum, $idnum, $ip, $port) = @_;
+    my ($proto, $ipvnum, $idnum, $ip, $port_or_path) = @_;
     my $server = servername_id($proto, $ipvnum, $idnum);
     my $pid = 0;
     my $bonus="";
+    # $port_or_path contains a path for UNIX sockets, sws ignores the port
+    my $port = ($ipvnum eq "unix") ? 80 : $port_or_path;
 
     my $verifyout = "$LOGDIR/".
         servername_canon($proto, $ipvnum, $idnum) .'_verify.out';
@@ -735,6 +747,7 @@ sub verifyhttp {
     $flags .= "--silent ";
     $flags .= "--verbose ";
     $flags .= "--globoff ";
+    $flags .= "--unix-socket '$port_or_path' " if $ipvnum eq "unix";
     $flags .= "-1 "         if($has_axtls);
     $flags .= "--insecure " if($proto eq 'https');
     $flags .= "\"$proto://$ip:$port/${bonus}verifiedserver\"";
@@ -1174,7 +1187,7 @@ sub responsiveserver {
 # start the http server
 #
 sub runhttpserver {
-    my ($proto, $verbose, $alt, $port) = @_;
+    my ($proto, $verbose, $alt, $port_or_path) = @_;
     my $ip = $HOSTIP;
     my $ipvnum = 4;
     my $idnum = 1;
@@ -1201,6 +1214,10 @@ sub runhttpserver {
         $exe = "python $srcdir/http_pipe.py";
         $verbose_flag .= "1 ";
     }
+    elsif($alt eq "unix") {
+        # IP (protocol) is mutually exclusive with UNIX sockets
+        $ipvnum = "unix";
+    }
 
     $server = servername_id($proto, $ipvnum, $idnum);
 
@@ -1226,7 +1243,12 @@ sub runhttpserver {
     $flags .= $verbose_flag if($debugprotocol);
     $flags .= "--pidfile \"$pidfile\" --logfile \"$logfile\" ";
     $flags .= "--id $idnum " if($idnum > 1);
-    $flags .= "--ipv$ipvnum --port $port --srcdir \"$srcdir\"";
+    if($ipvnum eq "unix") {
+        $flags .= "--unix-socket '$port_or_path' ";
+    } else {
+        $flags .= "--ipv$ipvnum --port $port_or_path ";
+    }
+    $flags .= "--srcdir \"$srcdir\"";
 
     my $cmd = "$exe $flags";
     my ($httppid, $pid2) = startnew($cmd, $pidfile, 15, 0);
@@ -1241,7 +1263,7 @@ sub runhttpserver {
     }
 
     # Server is up. Verify that we can speak to it.
-    my $pid3 = verifyserver($proto, $ipvnum, $idnum, $ip, $port);
+    my $pid3 = verifyserver($proto, $ipvnum, $idnum, $ip, $port_or_path);
     if(!$pid3) {
         logmsg "RUN: $srvrname server failed verification\n";
         # failed to talk to it properly. Kill the server and return failure
@@ -2082,7 +2104,7 @@ sub runsocksserver {
 # be used to verify that a server present in %run hash is still functional
 #
 sub responsive_http_server {
-    my ($proto, $verbose, $alt, $port) = @_;
+    my ($proto, $verbose, $alt, $port_or_path) = @_;
     my $ip = $HOSTIP;
     my $ipvnum = 4;
     my $idnum = 1;
@@ -2095,8 +2117,12 @@ sub responsive_http_server {
     elsif($alt eq "proxy") {
         $idnum = 2;
     }
+    elsif($alt eq "unix") {
+        # IP (protocol) is mutually exclusive with UNIX sockets
+        $ipvnum = "unix";
+    }
 
-    return &responsiveserver($proto, $ipvnum, $idnum, $ip, $port);
+    return &responsiveserver($proto, $ipvnum, $idnum, $ip, $port_or_path);
 }
 
 #######################################################################
@@ -2346,9 +2372,10 @@ sub checksystem {
             @protocols = split(' ', lc($1));
 
             # Generate a "proto-ipv6" version of each protocol to match the
-            # IPv6 <server> name. This works even if IPv6 support isn't
+            # IPv6 <server> name and a "proto-unix" to match the variant which
+            # uses UNIX domain sockets. This works even if support isn't
             # compiled in because the <features> test will fail.
-            push @protocols, map($_ . '-ipv6', @protocols);
+            push @protocols, map(("$_-ipv6", "$_-unix"), @protocols);
 
             # 'http-proxy' is used in test cases to do CONNECT through
             push @protocols, 'http-proxy';
@@ -2384,6 +2411,9 @@ sub checksystem {
             if($feat =~ /IPv6/i) {
                 $has_ipv6 = 1;
             }
+            if($feat =~ /unix-sockets/i) {
+                $has_unix = 1;
+            }
             if($feat =~ /libz/i) {
                 $has_libz = 1;
             }
@@ -2517,6 +2547,12 @@ sub checksystem {
         }
     }
 
+    if($has_unix) {
+        # client has UNIX sockets support, check whether the HTTP server has it
+        my @sws = `server/sws --version`;
+        $http_unix = 1 if($sws[0] =~ /unix/);
+    }
+
     if(!$has_memory_tracking && $torture) {
         die "can't run torture tests since curl was built without ".
             "TrackMemory feature (--enable-curldebug)";
@@ -2548,6 +2584,7 @@ sub checksystem {
     logmsg sprintf("  track memory: %s\n", $has_memory_tracking?"ON ":"OFF");
     logmsg sprintf("* valgrind:     %8s", $valgrind?"ON ":"OFF");
     logmsg sprintf("  HTTP IPv6     %s\n", $http_ipv6?"ON ":"OFF");
+    logmsg sprintf("* HTTP UNIX     %s\n", $http_unix?"ON ":"OFF");
     logmsg sprintf("* FTP IPv6      %8s", $ftp_ipv6?"ON ":"OFF");
     logmsg sprintf("  Libtool lib:  %s\n", $libtool?"ON ":"OFF");
     logmsg sprintf("* Shared build:      %-3s", $has_shared);
@@ -2600,6 +2637,13 @@ sub checksystem {
     }
     logmsg sprintf("*   HTTP-PIPE/%d \n", $HTTPPIPEPORT);
 
+    if($has_unix) {
+        logmsg "* UNIX socket paths:\n";
+        if($http_unix) {
+            logmsg sprintf("*   HTTP-UNIX:%s\n", $HTTPUNIXPATH);
+        }
+    }
+
     $has_textaware = ($^O eq 'MSWin32') || ($^O eq 'msys');
 
     logmsg "***************************************** \n";
@@ -2648,6 +2692,10 @@ sub subVariables {
   $$thing =~ s/%TFTP6PORT/$TFTP6PORT/g;
   $$thing =~ s/%TFTPPORT/$TFTPPORT/g;
 
+  # server UNIX domain socket paths
+
+  $$thing =~ s/%HTTPUNIXPATH/$HTTPUNIXPATH/g;
+
   # client IP addresses
 
   $$thing =~ s/%CLIENT6IP/$CLIENT6IP/g;
@@ -2924,6 +2972,9 @@ sub singletest {
             elsif($1 eq "socks") {
                 next;
             }
+            elsif($1 eq "unix-sockets") {
+                next if $has_unix;
+            }
             # See if this "feature" is in the list of supported protocols
             elsif (grep /^\Q$1\E$/i, @protocols) {
                 next;
@@ -2996,6 +3047,9 @@ sub singletest {
                         next;
                     }
                 }
+                elsif($1 eq "unix-sockets") {
+                    next if !$has_unix;
+                }
                 elsif($1 eq "libz") {
                     if(!$has_libz) {
                         next;
@@ -3567,11 +3621,11 @@ sub singletest {
         my @killservers;
         foreach my $server (@killtestservers) {
             chomp $server;
-            if($server =~ /^(ftp|http|imap|pop3|smtp)s((\d*)(-ipv6|))$/) {
+            if($server =~ /^(ftp|http|imap|pop3|smtp)s((\d*)(-ipv6|-unix|))$/) {
                 # given a stunnel ssl server, also kill non-ssl underlying one
                 push @killservers, "${1}${2}";
             }
-            elsif($server =~ /^(ftp|http|imap|pop3|smtp)((\d*)(-ipv6|))$/) {
+            elsif($server =~ /^(ftp|http|imap|pop3|smtp)((\d*)(-ipv6|-unix|))$/) {
                 # given a non-ssl server, also kill stunnel piggybacking one
                 push @killservers, "${1}s${2}";
             }
@@ -4085,7 +4139,7 @@ sub startservers {
         $what =~ s/[^a-z0-9-]//g;
 
         my $certfile;
-        if($what =~ /^(ftp|http|imap|pop3|smtp)s((\d*)(-ipv6|))$/) {
+        if($what =~ /^(ftp|http|imap|pop3|smtp)s((\d*)(-ipv6|-unix|))$/) {
             $certfile = ($whatlist[1]) ? $whatlist[1] : 'stunnel.pem';
         }
 
@@ -4440,6 +4494,22 @@ sub startservers {
                 }
             }
         }
+        elsif($what eq "http-unix") {
+            if($torture && $run{'http-unix'} &&
+               !responsive_http_server("http", $verbose, "unix", $HTTPUNIXPATH)) {
+                stopserver('http-unix');
+            }
+            if(!$run{'http-unix'}) {
+                ($pid, $pid2) = runhttpserver("http", $verbose, "unix",
+                                              $HTTPUNIXPATH);
+                if($pid <= 0) {
+                    return "failed starting HTTP-unix server";
+                }
+                logmsg sprintf("* pid http-unix => %d %d\n", $pid, $pid2)
+                    if($verbose);
+                $run{'http-unix'}="$pid $pid2";
+            }
+        }
         elsif($what eq "none") {
             logmsg "* starts no server\n" if ($verbose);
         }
@@ -4892,6 +4962,7 @@ $HTTPTLSPORT     = $base++; # HTTP TLS (non-stunnel) server port
 $HTTPTLS6PORT    = $base++; # HTTP TLS (non-stunnel) IPv6 server port
 $HTTPPROXYPORT   = $base++; # HTTP proxy port, when using CONNECT
 $HTTPPIPEPORT    = $base++; # HTTP pipelining port
+$HTTPUNIXPATH    = 'http.sock'; # HTTP server UNIX domain socket path
 
 #######################################################################
 # clear and create logging directory:
diff --git a/tests/serverhelp.pm b/tests/serverhelp.pm
index b0b5b74..220fba9 100644
--- a/tests/serverhelp.pm
+++ b/tests/serverhelp.pm
@@ -109,8 +109,8 @@ sub servername_str {
 
     $ipver = (not $ipver) ? 'ipv4' : lc($ipver);
     die "unsupported IP version: '$ipver'" unless($ipver &&
-        ($ipver =~ /^(4|6|ipv4|ipv6|-ipv4|-ipv6)$/));
-    $ipver = ($ipver =~ /6$/) ? '-IPv6' : '';
+        ($ipver =~ /^(4|6|ipv4|ipv6|-ipv4|-ipv6|unix)$/));
+    $ipver = ($ipver =~ /6$/) ? '-IPv6' : (($ipver =~ /unix$/) ? '-unix' : '');
 
     $idnum = 1 if(not $idnum);
     die "unsupported ID number: '$idnum'" unless($idnum &&
-- 
2.1.3
-------------------------------------------------------------------
List admin: http://cool.haxx.se/list/listinfo/curl-library
Etiquette:  http://curl.haxx.se/mail/etiquette.html
Received on 2014-11-28