diff --git a/tests/FILEFORMAT b/tests/FILEFORMAT index a24007cfb..1637357c8 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 1e5a87973..7ef7f81d2 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 a38c3cebd..1b8c3d284 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 46a78c48d..b1bb558fc 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 name. This works even if IPv6 support isn't + # IPv6 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 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 b0b5b7492..220fba926 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 &&