X-Git-Url: https://git.exim.org/exim.git/blobdiff_plain/fc96d1e87f4a25db713996b2ae2daf8a0e62575d..d63a9563033c690d8b7f572780b332fa9620ef3b:/test/runtest diff --git a/test/runtest b/test/runtest index f4e6bc7a5..71d4434f1 100755 --- a/test/runtest +++ b/test/runtest @@ -14,6 +14,7 @@ ############################################################################### #use strict; +use 5.010; use Errno; use FileHandle; use Socket; @@ -38,6 +39,7 @@ $gnutls_dh_bits_normal = 2236; $cf = "bin/cf -exact"; $cr = "\r"; $debug = 0; +$flavour = 'FOO'; $force_continue = 0; $force_update = 0; $log_failed_filename = "failed-summary.log"; @@ -45,7 +47,7 @@ $more = "less -XF"; $optargs = ""; $save_output = 0; $server_opts = ""; -$flavour = 'FOO'; +$valgrind = 0; $have_ipv4 = 1; $have_ipv6 = 1; @@ -81,13 +83,16 @@ $parm_port_d3 = 1227; # Additional for daemon $parm_port_d4 = 1228; # Additional for daemon # Manually set locale -$ENV{'LC_ALL'} = 'C'; +$ENV{LC_ALL} = 'C'; # In some environments USER does not exists, but we # need it for some test(s) $ENV{USER} = getpwuid($>) if not exists $ENV{USER}; +my ($parm_configure_owner, $parm_configure_group); +my ($parm_ipv4, $parm_ipv6); +my $parm_hostname; ############################################################################### ############################################################################### @@ -348,7 +353,7 @@ $spid = "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx"; # that are specific to certain file types, though there are also some of those # inline too. -while() +LINE: while() { RESET_AFTER_EXTRA_LINE_READ: # Custom munges @@ -426,7 +431,7 @@ RESET_AFTER_EXTRA_LINE_READ: # File descriptor numbers may vary s/^writing data block fd=\d+/writing data block fd=dddd/; - s/running as transport filter: write=\d+ read=\d+/running as transport filter: write=dddd read=dddd/; + s/(running as transport filter:) fd_write=\d+ fd_read=\d+/$1 fd_write=dddd fd_read=dddd/; # ======== Dumpdb output ======== @@ -652,6 +657,9 @@ RESET_AFTER_EXTRA_LINE_READ: s/waiting for children of \d+/waiting for children of pppp/; s/waiting for (\S+) \(\d+\)/waiting for $1 (pppp)/; + # The spool header file name varies with PID + s%^(Writing spool header file: .*/hdr).[0-9]{1,5}%$1.pppp%; + # ======== Port numbers ======== # Incoming port numbers may vary, but not in daemon startup line. @@ -754,10 +762,6 @@ RESET_AFTER_EXTRA_LINE_READ: s/Delivered\s+\d+/Delivered nnn/; - # ======== Values in spool space failure message ======== - s/space=\d+ inodes=[+-]?\d+/space=xxxxx inodes=xxxxx/; - - # ======== Filter sizes ======== # The sizes of filter files may vary because of the substitution of local # filenames, logins, etc. @@ -771,6 +775,7 @@ RESET_AFTER_EXTRA_LINE_READ: # different wording in the error messages, so we cannot compare them. s/(TLS error on connection (?:from .* )?\(SSL_\w+\): error:)(.*)/$1 <>/; + next if /SSL verify error: depth=0 error=certificate not trusted/; # ======== Maildir things ======== # timestamp output in maildir processing @@ -859,6 +864,9 @@ RESET_AFTER_EXTRA_LINE_READ: next if /^SSL info: SSLv3 read server key exchange A/; next if /SSL verify error: depth=0 error=certificate not trusted/; s/SSL3_READ_BYTES/ssl3_read_bytes/; + + # gnutls version variances + next if /^Error in the pull function./; } # ======== stderr ======== @@ -999,6 +1007,29 @@ RESET_AFTER_EXTRA_LINE_READ: while () { last if !/^\s/; } } + # remote port numbers vary + s/(Connection request from 127.0.0.1 port) \d{1,5}/$1 sssss/; + + # Skip hosts_require_dane checks when the options + # are unset, because dane ain't always there. + + next if /in\shosts_require_dane\?\sno\s\(option\sunset\)/x; + + # SUPPORT_PROXY + next if /host in hosts_proxy\?/; + + # Experimental_International + next if / in smtputf8_advertise_hosts\? no \(option unset\)/; + + # Environment cleaning + next if /\w+ in keep_environment\? (yes|no)/; + + # Sizes vary with test hostname + s/^cmd buf flush \d+ bytes$/cmd buf flush ddd bytes/; + + # Spool filesystem free space changes on different systems. + s/^((?:spool|log) directory space =) -?\d+K (inodes =)\s*-?\d+/$1 nnnnnK $2 nnnnn/; + # When Exim is checking the size of directories for maildir, it uses # the check_dir_size() function to scan directories. Of course, the order # of the files that are obtained using readdir() varies from system to @@ -1020,20 +1051,6 @@ RESET_AFTER_EXTRA_LINE_READ: @saved = (); } - # remote port numbers vary - s/(Connection request from 127.0.0.1 port) \d{1,5}/$1 sssss/; - - # Skip hosts_require_dane checks when the options - # are unset, because dane ain't always there. - - next if /in\shosts_require_dane\?\sno\s\(option\sunset\)/x; - - # SUPPORT_PROXY - next if /host in hosts_proxy\?/; - - # Experimental_International - next if / in smtputf8_advertise_hosts\? no \(option unset\)/; - # Skip some lines that Exim puts out at the start of debugging output # because they will be different in different binaries. @@ -1048,6 +1065,7 @@ RESET_AFTER_EXTRA_LINE_READ: /^log selectors =/ || /^cwd=/ || /^Fixed never_users:/ || + /^Configure owner:/ || /^Size of off_t:/ ); @@ -1389,9 +1407,27 @@ $munges = { 'mail' => '/^(X-(Remote-MTA-(smtp-greeting|helo-response)|Exim-Diagnostic|(body|message)-linecount):|Remote-MTA: X-ip;)/' }, + 'optional_config' => + { 'stdout' => '/^( + dkim_(canon|domain|private_key|selector|sign_headers|strict) + |gnutls_require_(kx|mac|protocols) + |hosts_(requ(est|ire)|try)_(dane|ocsp) + |hosts_(avoid|nopass|require|verify_avoid)_tls + |socks_proxy + |tls_[^ ]* + )($|[ ]=)/x' }, + 'sys_bindir' => { 'mainlog' => 's%/(usr/)?bin/%SYSBINDIR/%' }, + 'sync_check_data' => + { 'mainlog' => 's/^(.* SMTP protocol synchronization error .* next input=.{8}).*$/$1/', + 'rejectlog' => 's/^(.* SMTP protocol synchronization error .* next input=.{8}).*$/$1/'}, + + 'debuglog_stdout' => + { 'stdout' => 's/^\d\d:\d\d:\d\d\s+\d+ //; + s/Process \d+ is ready for new message/Process pppp is ready for new message/' + }, }; @@ -1667,6 +1703,8 @@ my($commandnameref) = $_[3]; my($aux_info) = $_[4]; my($yield) = 1; +our %ENV = map { $_ => $ENV{$_} } grep { /^(?:USER|SHELL|PATH|TERM|EXIM_TEST_.*)$/ } keys %ENV; + if (/^(\d+)\s*$/) # Handle unusual return code { my($r) = $_[2]; @@ -1932,7 +1970,7 @@ if (/^sleep\s+(.*)$/) # Various Unix management commands are recognized if (/^(ln|ls|du|mkdir|mkfifo|touch|cp|cat)\s/ || - /^sudo (rmdir|rm|chown|chmod)\s/) + /^sudo\s(rmdir|rm|mv|chown|chmod)\s/) { run_system("$_ >>test-stdout 2>>test-stderr"); return 1; @@ -1953,6 +1991,7 @@ if (/^(ln|ls|du|mkdir|mkfifo|touch|cp|cat)\s/ || # command, triggered by $server_pid being non-zero. The server sends its output # to a different file. The variable $server_opts, if not empty, contains # options to disable IPv4 or IPv6 if necessary. +# This works because "server" swallows its stdin before waiting for a connection. if (/^server\s+(.*)$/) { @@ -2070,7 +2109,7 @@ if (/^client/ || /^(sudo\s+)?perl\b/) # not drop privilege when -C and -D options are present. To run the exim # command as root, we use sudo. -elsif (/^([A-Z_]+=\S+\s+)?(\d+)?\s*(sudo(?:\s+-u\s+(\w+))?\s+)?exim(_\S+)?\s+(.*)$/) +elsif (/^((?i:[A-Z\d_]+=\S+\s+)+)?(\d+)?\s*(sudo(?:\s+-u\s+(\w+))?\s+)?exim(_\S+)?\s+(.*)$/) { $args = $6; my($envset) = (defined $1)? $1 : ""; @@ -2131,7 +2170,10 @@ elsif (/^([A-Z_]+=\S+\s+)?(\d+)?\s*(sudo(?:\s+-u\s+(\w+))?\s+)?exim(_\S+)?\s+(.* $args =~ s/(?:^|\s)-d\S*// if $optargs =~ /(?:^|\s)-d/; - $cmd = "$envset$sudo$parm_cwd/eximdir/exim$special$optargs " . + my $opt_valgrind = $valgrind ? "valgrind --leak-check=yes --suppressions=$parm_cwd/aux-fixed/valgrind.supp " : ""; + + $cmd = "$envset$sudo$opt_valgrind" . + "$parm_cwd/eximdir/exim$special$optargs " . "-DEXIM_PATH=$parm_cwd/eximdir/exim$special " . "-C $parm_cwd/test-config $args " . ">>test-stdout 2>>test-stderr"; @@ -2301,7 +2343,7 @@ return $yield; # Ran command and waited ############################################################################### ############################################################################### -# Here beginneth the Main Program ... +# Here begins the Main Program ... ############################################################################### ############################################################################### @@ -2331,7 +2373,7 @@ umask 022; # Check for the "less" command # ################################################## -$more = "more" if system("which less >/dev/null 2>&1") != 0; +$more = 'more' if system('which less >/dev/null 2>&1') != 0; @@ -2340,7 +2382,7 @@ $more = "more" if system("which less >/dev/null 2>&1") != 0; ################################################## print "You need to have sudo access to root to run these tests. Checking ...\n"; -if (system("sudo date >/dev/null") != 0) +if (system('sudo true >/dev/null') != 0) { die "** Test for sudo failed: testing abandoned.\n"; } @@ -2386,6 +2428,7 @@ while (@ARGV > 0 && $ARGV[0] =~ /^-/) if ($arg eq "-NOIPV4") { $have_ipv4 = 0; next; } if ($arg eq "-NOIPV6") { $have_ipv6 = 0; next; } if ($arg eq "-KEEP") { $save_output = 1; next; } + if ($arg eq "-VALGRIND") { $valgrind = 1; next; } if ($arg =~ /^-FLAVOU?R$/) { $flavour = shift; next; } } $optargs .= " $arg"; @@ -2522,6 +2565,8 @@ while() $parm_eximuser = $1 if /^exim_user = (.*)$/; $parm_eximgroup = $1 if /^exim_group = (.*)$/; $parm_trusted_config_list = $1 if /^TRUSTED_CONFIG_LIST:.*?"(.*?)"$/; + ($parm_configure_owner, $parm_configure_group) = ($1, $2) + if /^Configure owner:\s*(\d+):(\d+)/; print "$_" if /wrong owner/; } close(EXIMINFO); @@ -2573,7 +2618,15 @@ else die "Unable to check the TRUSTED_CONFIG_LIST, seems to be empty?\n"; } -open(EXIMINFO, "$parm_exim -bV -C $parm_cwd/test-config -DDIR=$parm_cwd |") || +die "CONFIGURE_OWNER ($parm_configure_owner) does not match the user invoking $0 ($>)\n" + if $parm_configure_owner != $>; + +die "CONFIGURE_GROUP ($parm_configure_group) does not match the group invoking $0 ($))\n" + if 0020 & (stat "$parm_cwd/test-config")[2] + and $parm_configure_group != $); + + +open(EXIMINFO, "$parm_exim -d-all+transport -bV -C $parm_cwd/test-config -DDIR=$parm_cwd |") || die "** Cannot run $parm_exim: $!\n"; print "-" x 78, "\n"; @@ -2582,7 +2635,7 @@ while () { my(@temp); - if (/^Exim version/) { print; } + if (/^(Exim|Library) version/) { print; } elsif (/^Size of off_t: (\d+)/) { @@ -2854,7 +2907,7 @@ if (defined $parm_support{'Content_Scanning'}) ################################################## # Check for redis # ################################################## -if (defined $parm_support{'Experimental_Redis'}) +if (defined $parm_lookups{'redis'}) { if (system("redis-server -v 2>/dev/null >/dev/null") == 0) { @@ -2971,38 +3024,29 @@ else # Find this host's IP addresses - there may be many, of course, but we keep # one of each type (IPv4 and IPv6). -$parm_ipv4 = ""; -$parm_ipv6 = ""; - -$local_ipv4 = ""; -$local_ipv6 = ""; - -open(IFCONFIG, "ifconfig -a|") || die "** Cannot run \"ifconfig\": $!\n"; -while (($parm_ipv4 eq "" || $parm_ipv6 eq "") && ($_ = )) +open(IFCONFIG, 'ip address|') # show *all*, addresses w/o label + or open(IFCONFIG, 'ifconfig -a|') # probably skips addresses w/o label + or die "** Cannot run 'ifconfig' or 'ip address': $!\n"; +while (not ($parm_ipv4 and $parm_ipv6) and defined($_ = )) { - my($ip); - if ($parm_ipv4 eq "" && - $_ =~ /^\s*inet(?:\saddr)?:?\s?(\d+\.\d+\.\d+\.\d+)\s/i) + if (not $parm_ipv4 and /^\s*inet(?:\saddr)?:?\s?(\d+\.\d+\.\d+\.\d+)(?:\/\d+)\s/i) { - $ip = $1; - next if ($ip =~ /^127\./ || $ip =~ /^10\./); - $parm_ipv4 = $ip; + next if $1 =~ /^(?:127|10)\./; + $parm_ipv4 = $1; } - if ($parm_ipv6 eq "" && - $_ =~ /^\s*inet6(?:\saddr)?:?\s?([abcdef\d:]+)/i) + if (not $parm_ipv6 and /^\s*inet6(?:\saddr)?:?\s?([abcdef\d:]+)(?:\/\d+)/i) { - $ip = $1; - next if ($ip eq "::1" || $ip =~ /^fe80/i); - $parm_ipv6 = $ip; + next if $1 eq '::1' or $1 =~ /^fe80/i; + $parm_ipv6 = $1; } } close(IFCONFIG); # Use private IP addresses if there are no public ones. -$parm_ipv4 = $local_ipv4 if ($parm_ipv4 eq ""); -$parm_ipv6 = $local_ipv6 if ($parm_ipv6 eq ""); +$parm_ipv4 //= '172.10.10.1'; +$parm_ipv6 //= 'fd0a:c2ea:abfa::1'; # If either type of IP address is missing, we need to set the value to # something other than empty, because that wrecks the substitutions. The value @@ -3012,7 +3056,7 @@ $parm_ipv6 = $local_ipv6 if ($parm_ipv6 eq ""); # of IPV4 or IPv6 can be simulated by command options, which force $have_ipv4 # and $have_ipv6 false. -if ($parm_ipv4 eq "") +if (not $parm_ipv4) { $have_ipv4 = 0; $parm_ipv4 = ""; @@ -3028,7 +3072,7 @@ else $parm_running{"IPv4"} = " "; } -if ($parm_ipv6 eq "") +if (not $parm_ipv6) { $have_ipv6 = 0; $parm_ipv6 = ""; @@ -3076,7 +3120,7 @@ if ($parm_ipv6 =~ /^[\da-f]/) # Find the host name, fully qualified. chomp($temp = `hostname`); -$parm_hostname = (gethostbyname($temp))[0]; +$parm_hostname = (gethostbyname($temp))[0] // $temp; $parm_hostname = "no.host.name.found" if $parm_hostname eq ""; print "Hostname is $parm_hostname\n"; @@ -3201,6 +3245,11 @@ if ($parm_caller_uid eq $parm_exim_uid) { tests_exit(-1, "Exim user ($parm_eximuser,$parm_exim_uid) cannot be " ."the same as caller ($parm_caller,$parm_caller_uid)"); } +if ($parm_caller_gid eq $parm_exim_gid) { + tests_exit(-1, "Exim group ($parm_eximgroup,$parm_exim_gid) cannot be " + ."the same as caller's ($parm_caller) group as it confuses " + ."results analysis"); +} print "The Exim user needs access to the test suite directory. Checking ..."; @@ -3684,8 +3733,9 @@ foreach $test (@test_list) my($subtest_startline) = $lineno; - # Now run the command. The function returns 0 if exim was run and waited - # for, 1 if any other command was run and waited for, and 2 if a command + # Now run the command. The function returns 0 for an inline command, + # 1 if a non-exim command was run and waited for, 2 if an exim + # command was run and waited for, and 3 if a command # was run and not waited for (usually a daemon or server startup). my($commandname) = ""; @@ -3748,7 +3798,15 @@ $0 = "[runtest $testno]"; $_ = $force_continue ? "c" : ; tests_exit(1) if /^q?$/i; log_failure($log_failed_filename, $testno, "exit code unexpected") if (/^c$/i && $force_continue); - print "... continue forced\n" if $force_continue; + if ($force_continue) + { + print "\nstderr tail:\n"; + print "===================\n"; + system("tail -20 test-stderr"); + print "===================\n"; + print "... continue forced\n"; + } + last if /^[rc]$/i; if (/^e$/i) {