# | (__| |_| | _ <| |___
# \___|\___/|_| \_\_____|
#
-# Copyright (C) 1998 - 2013, Daniel Stenberg, <daniel@haxx.se>, et al.
+# Copyright (C) 1998 - 2014, Daniel Stenberg, <daniel@haxx.se>, et al.
#
# This software is licensed as described in the file COPYING, which
# you should have received as part of this distribution. The terms
my $start;
my $ftpchecktime=1; # time it took to verify our test FTP server
-my $stunnel = checkcmd("stunnel4") || checkcmd("stunnel");
+my $stunnel = checkcmd("stunnel4") || checkcmd("tstunnel") || checkcmd("stunnel");
my $valgrind = checktestcmd("valgrind");
my $valgrind_logfile="--logfile";
my $valgrind_tool;
my $has_getrlimit; # set if system has getrlimit()
my $has_ntlm; # set if libcurl is built with NTLM support
my $has_ntlm_wb; # set if libcurl is built with NTLM delegation to winbind
+my $has_sspi; # set if libcurl is built with SSPI support
my $has_charconv;# set if libcurl is built with CharConv support
my $has_tls_srp; # set if libcurl is built with TLS-SRP support
my $has_metalink;# set if curl is built with Metalink support
my $has_yassl; # built with yassl
my $has_polarssl; # built with polarssl
my $has_axtls; # built with axTLS
-my $has_winssl; # built with WinSSL (Schannel/SSPI)
+my $has_winssl; # built with WinSSL (Secure Channel aka Schannel)
my $has_darwinssl;# build with DarwinSSL (Secure Transport)
my $has_shared = "unknown"; # built shared
+my $resolver; # string to hold the resolver backend
+my $has_cares; # if built with c-ares
+my $has_threadedres; # if built with threaded resolver
+
my $ssllib; # name of the lib we use (for human presentation)
my $has_crypto; # set if libcurl is built with cryptographic support
my $has_textaware; # set if running on a system that has a text mode concept
my $keepoutfiles; # keep stdout and stderr files after tests
my $listonly; # only list the tests
my $postmortem; # display detailed info about failed tests
+my $run_event_based; # run curl with --test-event to test the event API
my %run; # running server
my %doesntrun; # servers that don't work, identified by pidfile
# enable memory debugging if curl is compiled with it
$ENV{'CURL_MEMDEBUG'} = $memdump;
+$ENV{'CURL_ENTROPY'}="12345678";
+$ENV{'CURL_FORCETIME'}=1; # for debug NTLM magic
$ENV{'HOME'}=$pwd;
sub catch_zap {
sub runclient {
my ($cmd)=@_;
my $ret = system($cmd);
- print "CMD ($ret): $cmd\n" if($verbose);
+ print "CMD ($ret): $cmd\n" if($verbose && !$torture);
return $ret;
# This is one way to test curl on a remote machine
else {
$ret = runclient($testcmd);
}
- #logmsg "$_ Returned " . $ret >> 8 . "\n";
+ #logmsg "$_ Returned " . ($ret >> 8) . "\n";
# Now clear the variable again
delete $ENV{'CURL_MEMLIMIT'} if($ENV{'CURL_MEMLIMIT'});
# verify that it returns a proper error code, doesn't leak memory
# and doesn't core dump
- if($ret & 255) {
+ if(($ret & 255) || ($ret >> 8) >= 128) {
logmsg " system() returned $ret\n";
$fail=1;
}
if($proto eq "ftps") {
$extra .= "--insecure --ftp-ssl-control ";
}
- elsif($proto eq "smtp") {
- # SMTP is a bit different since it requires more options and it
- # has _no_ output!
- $extra .= "--mail-rcpt verifiedserver ";
- $extra .= "--mail-from fake ";
- $extra .= "--upload /dev/null ";
- $extra .= "--stderr - "; # move stderr to parse the verbose stuff
- }
my $flags = "--max-time $server_response_maxtime ";
$flags .= "--silent ";
close(FILE);
}
- if($data && ($data =~ /GNUTLS/) && open(FILE, "<$pidfile")) {
+ if($data && ($data =~ /(GNUTLS|GnuTLS)/) && open(FILE, "<$pidfile")) {
$pid=0+<FILE>;
close(FILE);
if($pid > 0) {
$flags .= "--http ";
$flags .= "--debug 1 " if($debugprotocol);
$flags .= "--port $port ";
+ $flags .= "--priority NORMAL:+SRP ";
$flags .= "--srppasswd $srcdir/certs/srp-verifier-db ";
$flags .= "--srppasswdconf $srcdir/certs/srp-verifier-conf";
@version = <VERSOUT>;
close(VERSOUT);
+ $resolver="stock";
for(@version) {
chomp;
$has_darwinssl=1;
$ssllib="DarwinSSL";
}
+ if ($libcurl =~ /ares/i) {
+ $has_cares=1;
+ $resolver="c-ares";
+ }
}
elsif($_ =~ /^Protocols: (.*)/i) {
# these are the protocols compiled in to this libcurl
if($feat =~ /NTLM/i) {
# NTLM enabled
$has_ntlm=1;
+ # Use this as a proxy for any cryptographic authentication
+ $has_crypto=1;
}
if($feat =~ /NTLM_WB/i) {
# NTLM delegation to winbind daemon ntlm_auth helper enabled
$has_ntlm_wb=1;
}
+ if($feat =~ /SSPI/i) {
+ # SSPI enabled
+ $has_sspi=1;
+ }
if($feat =~ /CharConv/i) {
# CharConv enabled
$has_charconv=1;
# Metalink enabled
$has_metalink=1;
}
+ if($feat =~ /AsynchDNS/i) {
+ if(!$has_cares) {
+ # this means threaded resolver
+ $has_threadedres=1;
+ $resolver="threaded";
+ }
+ }
}
#
# Test harness currently uses a non-stunnel server in order to
$has_shared = `sh $CURLCONFIG --built-shared`;
chomp $has_shared;
- # curl doesn't list cryptographic support separately, so assume it's
- # always available
- $has_crypto=1;
-
my $hostname=join(' ', runclientoutput("hostname"));
my $hosttype=join(' ', runclientoutput("uname -a"));
"* Host: $hostname",
"* System: $hosttype");
+ if($has_memory_tracking && $has_threadedres) {
+ $has_memory_tracking = 0;
+ logmsg("*\n",
+ "*** DISABLES memory tracking when using threaded resolver\n",
+ "*\n");
+ }
+
logmsg sprintf("* Server SSL: %8s", $stunnel?"ON ":"OFF");
logmsg sprintf(" libcurl SSL: %s\n", $ssl_version?"ON ":"OFF");
logmsg sprintf("* debug build: %8s", $debug_build?"ON ":"OFF");
logmsg sprintf(" HTTP IPv6 %s\n", $http_ipv6?"ON ":"OFF");
logmsg sprintf("* FTP IPv6 %8s", $ftp_ipv6?"ON ":"OFF");
logmsg sprintf(" Libtool lib: %s\n", $libtool?"ON ":"OFF");
- logmsg sprintf("* Shared build: %s\n", $has_shared);
+ logmsg sprintf("* Shared build: %-3s", $has_shared);
+ logmsg sprintf(" Resolver: %s\n", $resolver);
if($ssl_version) {
logmsg sprintf("* SSL library: %13s\n", $ssllib);
}
# Run a single specified test case
#
sub singletest {
- my ($testnum, $count, $total)=@_;
+ my ($evbased, # 1 means switch on if possible (and "curl" is tested)
+ # returns "not a test" if it can't be used for this test
+ $testnum,
+ $count,
+ $total)=@_;
my @what;
my $why;
@what = getpart("client", "features");
}
+ # We require a feature to be present
for(@what) {
my $f = $_;
$f =~ s/\s//g;
- $feature{$f}=$f; # we require this feature
+ if($f =~ /^([^!].*)$/) {
+ # Store the feature for later
+ $feature{$1} = $1;
- if($f eq "SSL") {
- if($ssl_version) {
- next;
+ if($1 eq "SSL") {
+ if($ssl_version) {
+ next;
+ }
}
- }
- elsif($f eq "OpenSSL") {
- if($has_openssl) {
- next;
+ elsif($1 eq "OpenSSL") {
+ if($has_openssl) {
+ next;
+ }
}
- }
- elsif($f eq "GnuTLS") {
- if($has_gnutls) {
- next;
+ elsif($1 eq "GnuTLS") {
+ if($has_gnutls) {
+ next;
+ }
}
- }
- elsif($f eq "NSS") {
- if($has_nss) {
- next;
+ elsif($1 eq "NSS") {
+ if($has_nss) {
+ next;
+ }
}
- }
- elsif($f eq "axTLS") {
- if($has_axtls) {
- next;
+ elsif($1 eq "axTLS") {
+ if($has_axtls) {
+ next;
+ }
}
- }
- elsif($f eq "WinSSL") {
- if($has_winssl) {
- next;
+ elsif($1 eq "WinSSL") {
+ if($has_winssl) {
+ next;
+ }
}
- }
- elsif($f eq "DarwinSSL") {
- if($has_darwinssl) {
- next;
+ elsif($1 eq "DarwinSSL") {
+ if($has_darwinssl) {
+ next;
+ }
}
- }
- elsif($f eq "unittest") {
- if($debug_build) {
- next;
+ elsif($1 eq "unittest") {
+ if($debug_build) {
+ next;
+ }
}
- }
- elsif($f eq "debug") {
- if($debug_build) {
- next;
+ elsif($1 eq "debug") {
+ if($debug_build) {
+ next;
+ }
}
- }
- elsif($f eq "TrackMemory") {
- if($has_memory_tracking) {
- next;
+ elsif($1 eq "TrackMemory") {
+ if($has_memory_tracking) {
+ next;
+ }
}
- }
- elsif($f eq "large_file") {
- if($large_file) {
- next;
+ elsif($1 eq "large_file") {
+ if($large_file) {
+ next;
+ }
}
- }
- elsif($f eq "idn") {
- if($has_idn) {
- next;
+ elsif($1 eq "idn") {
+ if($has_idn) {
+ next;
+ }
}
- }
- elsif($f eq "ipv6") {
- if($has_ipv6) {
- next;
+ elsif($1 eq "ipv6") {
+ if($has_ipv6) {
+ next;
+ }
}
- }
- elsif($f eq "libz") {
- if($has_libz) {
- next;
+ elsif($1 eq "libz") {
+ if($has_libz) {
+ next;
+ }
}
- }
- elsif($f eq "NTLM") {
- if($has_ntlm) {
- next;
+ elsif($1 eq "NTLM") {
+ if($has_ntlm) {
+ next;
+ }
}
- }
- elsif($f eq "NTLM_WB") {
- if($has_ntlm_wb) {
- next;
+ elsif($1 eq "NTLM_WB") {
+ if($has_ntlm_wb) {
+ next;
+ }
}
- }
- elsif($f eq "getrlimit") {
- if($has_getrlimit) {
- next;
+ elsif($1 eq "SSPI") {
+ if($has_sspi) {
+ next;
+ }
}
- }
- elsif($f eq "crypto") {
- if($has_crypto) {
+ elsif($1 eq "getrlimit") {
+ if($has_getrlimit) {
+ next;
+ }
+ }
+ elsif($1 eq "crypto") {
+ if($has_crypto) {
+ next;
+ }
+ }
+ elsif($1 eq "TLS-SRP") {
+ if($has_tls_srp) {
+ next;
+ }
+ }
+ elsif($1 eq "Metalink") {
+ if($has_metalink) {
+ next;
+ }
+ }
+ elsif($1 eq "socks") {
next;
}
- }
- elsif($f eq "TLS-SRP") {
- if($has_tls_srp) {
+ # See if this "feature" is in the list of supported protocols
+ elsif (grep /^\Q$1\E$/i, @protocols) {
next;
}
+
+ $why = "curl lacks $1 support";
+ last;
}
- elsif($f eq "Metalink") {
- if($has_metalink) {
+ }
+
+ # We require a feature to not be present
+ if(!$why) {
+ for(@what) {
+ my $f = $_;
+ $f =~ s/\s//g;
+
+ if($f =~ /^!(.*)$/) {
+ if($1 eq "SSL") {
+ if(!$ssl_version) {
+ next;
+ }
+ }
+ elsif($1 eq "OpenSSL") {
+ if(!$has_openssl) {
+ next;
+ }
+ }
+ elsif($1 eq "GnuTLS") {
+ if(!$has_gnutls) {
+ next;
+ }
+ }
+ elsif($1 eq "NSS") {
+ if(!$has_nss) {
+ next;
+ }
+ }
+ elsif($1 eq "axTLS") {
+ if(!$has_axtls) {
+ next;
+ }
+ }
+ elsif($1 eq "WinSSL") {
+ if(!$has_winssl) {
+ next;
+ }
+ }
+ elsif($1 eq "DarwinSSL") {
+ if(!$has_darwinssl) {
+ next;
+ }
+ }
+ elsif($1 eq "TrackMemory") {
+ if(!$has_memory_tracking) {
+ next;
+ }
+ }
+ elsif($1 eq "large_file") {
+ if(!$large_file) {
+ next;
+ }
+ }
+ elsif($1 eq "idn") {
+ if(!$has_idn) {
+ next;
+ }
+ }
+ elsif($1 eq "ipv6") {
+ if(!$has_ipv6) {
+ next;
+ }
+ }
+ elsif($1 eq "libz") {
+ if(!$has_libz) {
+ next;
+ }
+ }
+ elsif($1 eq "NTLM") {
+ if(!$has_ntlm) {
+ next;
+ }
+ }
+ elsif($1 eq "NTLM_WB") {
+ if(!$has_ntlm_wb) {
+ next;
+ }
+ }
+ elsif($1 eq "SSPI") {
+ if(!$has_sspi) {
+ next;
+ }
+ }
+ elsif($1 eq "getrlimit") {
+ if(!$has_getrlimit) {
+ next;
+ }
+ }
+ elsif($1 eq "crypto") {
+ if(!$has_crypto) {
+ next;
+ }
+ }
+ elsif($1 eq "TLS-SRP") {
+ if(!$has_tls_srp) {
+ next;
+ }
+ }
+ elsif($1 eq "Metalink") {
+ if(!$has_metalink) {
+ next;
+ }
+ }
+ else {
+ next;
+ }
+ }
+ else {
next;
}
- }
- elsif($f eq "socks") {
- next;
- }
- # See if this "feature" is in the list of supported protocols
- elsif (grep /^\Q$f\E$/i, @protocols) {
- next;
- }
- $why = "curl lacks $f support";
- last;
+ $why = "curl has $1 support";
+ last;
+ }
}
if(!$why) {
my @keywords = getpart("info", "keywords");
my $match;
my $k;
+
+ if(!$keywords[0]) {
+ $why = "missing the <keywords> section!";
+ }
+
for $k (@keywords) {
chomp $k;
if ($disabled_keywords{$k}) {
my @reply = getpart("reply", "data");
my @replycheck = getpart("reply", "datacheck");
+ my %replyattr = getpartattr("reply", "data");
+ my %replycheckattr = getpartattr("reply", "datacheck");
+
if (@replycheck) {
# we use this file instead to check the final output against
- my %hash = getpartattr("reply", "datacheck");
- if($hash{'nonewline'}) {
+ if($replycheckattr{'nonewline'}) {
# Yes, we must cut off the final newline from the final line
# of the datacheck
chomp($replycheck[$#replycheck]);
}
+ if($replycheckattr{'mode'}) {
+ $replyattr{'mode'} = $replycheckattr{'mode'};
+ }
@reply=@replycheck;
}
my $CMDLINE;
my $cmdargs;
my $cmdtype = $cmdhash{'type'} || "default";
+ my $fail_due_event_based = $evbased;
if($cmdtype eq "perl") {
# run the command line prepended with "perl"
$cmdargs ="$cmd";
$disablevalgrind=1;
}
elsif(!$tool) {
- # run curl, add --verbose for debug information output
+ # run curl, add suitable command line options
$cmd = "-1 ".$cmd if(exists $feature{"SSL"} && ($has_axtls));
my $inc="";
if((!$cmdhash{'option'}) || ($cmdhash{'option'} !~ /no-include/)) {
- $inc = "--include ";
+ $inc = " --include";
}
- $cmdargs ="$out $inc--trace-ascii log/trace$testnum --trace-time $cmd";
+ $cmdargs = "$out$inc ";
+ $cmdargs .= "--trace-ascii log/trace$testnum ";
+ $cmdargs .= "--trace-time ";
+ if($evbased) {
+ $cmdargs .= "--test-event ";
+ $fail_due_event_based--;
+ }
+ $cmdargs .= $cmd;
}
else {
$cmdargs = " $cmd"; # $cmd is the command line for the test file
$DBGCURL=$CMDLINE;
}
+ if($gdbthis) {
+ # gdb is incompatible with valgrind, so disable it when debugging
+ # Perhaps a better approach would be to run it under valgrind anyway
+ # with --db-attach=yes or --vgdb=yes.
+ $disablevalgrind=1;
+ }
+
+ if($fail_due_event_based) {
+ logmsg "This test cannot run event based\n";
+ return -1;
+ }
+
my @stdintest = getpart("client", "stdin");
if(@stdintest) {
$valgrindcmd .= "$valgrind_tool " if($valgrind_tool);
$valgrindcmd .= "--leak-check=yes ";
$valgrindcmd .= "--suppressions=$srcdir/valgrind.supp ";
+ # $valgrindcmd .= "--gen-suppressions=all ";
$valgrindcmd .= "--num-callers=16 ";
$valgrindcmd .= "${valgrind_logfile}=$LOGDIR/valgrind$testnum";
$CMDLINE = "$valgrindcmd $CMDLINE";
my $filemode=$hash{'mode'};
if($filemode && ($filemode eq "text") && $has_textaware) {
# text mode when running on windows: fix line endings
- map s/\r\n/\n/g, @actual;
+ map s/\r\n/\n/g, @validstdout;
+ map s/\n/\r\n/g, @validstdout;
}
if($hash{'nonewline'}) {
$ok .= "-"; # stdout not checked
}
- my %replyattr = getpartattr("reply", "data");
- if(!$replyattr{'nocheck'} && (@reply || $replyattr{'sendzero'})) {
- # verify the received data
- my @out = loadarray($CURLOUT);
- my %hash = getpartattr("reply", "data");
- # get the mode attribute
- my $filemode=$hash{'mode'};
- if($filemode && ($filemode eq "text") && $has_textaware) {
- # text mode when running on windows: fix line endings
- map s/\r\n/\n/g, @out;
- }
-
- $res = compare($testnum, $testname, "data", \@out, \@reply);
- if ($res) {
- return 1;
- }
- $ok .= "d";
- }
- else {
- $ok .= "-"; # data not checked
- }
-
- if(@upload) {
- # verify uploaded data
- my @out = loadarray("$LOGDIR/upload.$testnum");
- $res = compare($testnum, $testname, "upload", \@out, \@upload);
- if ($res) {
- return 1;
- }
- $ok .= "u";
- }
- else {
- $ok .= "-"; # upload not checked
- }
-
if(@protocol) {
# Verify the sent request
my @out = loadarray($SERVERIN);
$ok .= "-"; # protocol not checked
}
+ if(!$replyattr{'nocheck'} && (@reply || $replyattr{'sendzero'})) {
+ # verify the received data
+ my @out = loadarray($CURLOUT);
+ # get the mode attribute
+ my $filemode=$replyattr{'mode'};
+ if($filemode && ($filemode eq "text") && $has_textaware) {
+ # text mode when running on windows: fix line endings
+ map s/\r\n/\n/g, @reply;
+ map s/\n/\r\n/g, @reply;
+ }
+
+ $res = compare($testnum, $testname, "data", \@out, \@reply);
+ if ($res) {
+ return 1;
+ }
+ $ok .= "d";
+ }
+ else {
+ $ok .= "-"; # data not checked
+ }
+
+ if(@upload) {
+ # verify uploaded data
+ my @out = loadarray("$LOGDIR/upload.$testnum");
+ $res = compare($testnum, $testname, "upload", \@out, \@upload);
+ if ($res) {
+ return 1;
+ }
+ $ok .= "u";
+ }
+ else {
+ $ok .= "-"; # upload not checked
+ }
+
if(@proxyprot) {
# Verify the sent proxy request
my @out = loadarray($PROXYIN);
my $filemode=$hash{'mode'};
if($filemode && ($filemode eq "text") && $has_textaware) {
- # text mode when running on windows means adding an extra
- # strip expression
- push @stripfile, "s/\r\n/\n/";
+ # text mode when running on windows: fix line endings
+ map s/\r\n/\n/g, @outfile;
+ map s/\n/\r\n/g, @outfile;
}
my $strip;
for $strip (@stripfile) {
chomp $strip;
+ my @newgen;
for(@generated) {
eval $strip;
+ if($_) {
+ push @newgen, $_;
+ }
}
+ # this is to get rid of array entries that vanished (zero
+ # length) because of replacements
+ @generated = @newgen;
}
@outfile = fixarray(@outfile);
else {
$ok .= "-"; # valgrind not checked
}
+ # add 'E' for event-based
+ $ok .= $evbased ? "E" : "-";
logmsg "$ok " if(!$short);
$DBGCURL=$CURL=$ARGV[1];
shift @ARGV;
}
+ elsif ($ARGV[0] eq "-vc") {
+ # use this path to a curl used to verify servers
+
+ # Particularly useful when you introduce a crashing bug somewhere in
+ # the development version as then it won't be able to run any tests
+ # since it can't verify the servers!
+
+ $VCURL=$ARGV[1];
+ shift @ARGV;
+ }
elsif ($ARGV[0] eq "-d") {
# have the servers display protocol output
$debugprotocol=1;
# continue anyway, even if a test fail
$anyway=1;
}
+ elsif($ARGV[0] eq "-e") {
+ # run the tests cases event based if possible
+ $run_event_based=1;
+ }
elsif($ARGV[0] eq "-p") {
$postmortem=1;
}
-am automake style output PASS/FAIL: [number] [name]
-t[N] torture (simulate memory alloc failures); N means fail Nth alloc
-v verbose output
+ -vc path use this curl only to verify the existing servers
[num] like "5 6 9" or " 5 to 22 " to run those tests only
[!num] like "!5 !6 !9" to disable those tests
[keyword] like "IPv6" to select only tests containing the key word
$TESTCASES .= " $n";
}
}
+else {
+ my $verified="";
+ map {
+ if (-e "$TESTDIR/test$_") {
+ $verified.="$_ ";
+ }
+ } split(" ", $TESTCASES);
+ if($verified eq "") {
+ print "No existing test cases were specified\n";
+ exit;
+ }
+ $TESTCASES = $verified;
+}
#######################################################################
# Start the command line log
$lasttest = $testnum if($testnum > $lasttest);
$count++;
- my $error = singletest($testnum, $count, scalar(@at));
+ my $error = singletest($run_event_based, $testnum, $count, scalar(@at));
if($error < 0) {
# not a test we can run
next;