X-Git-Url: https://git.exim.org/exim.git/blobdiff_plain/625cd9501315e1010ecbf8718c88c8b79ce09e94..9f6b3bf5187562bac4c96e3ed6a17740d01489fa:/test/runtest diff --git a/test/runtest b/test/runtest index 8a1e46edd..a2e61442e 100755 --- a/test/runtest +++ b/test/runtest @@ -29,10 +29,11 @@ use File::Basename; use Pod::Usage; use Getopt::Long; use FindBin qw'$RealBin'; +use File::Copy; use lib "$RealBin/lib"; use Exim::Runtest; -use Exim::Utils qw(uniq numerically); +use Exim::Utils qw(uniq numerically cp); use if $ENV{DEBUG} && scalar($ENV{DEBUG} =~ /\bruntest\b/) => 'Smart::Comments' => '####'; use if $ENV{DEBUG} && scalar($ENV{DEBUG} =~ /\bruntest\b/) => 'Data::Dumper'; @@ -368,6 +369,10 @@ my($is_mail) = $file =~ /mail/; $date = "\\d{2}-\\w{3}-\\d{4}\\s\\d{2}:\\d{2}:\\d{2}"; +# Debug time & pid + +$time_pid = "(?:\\d{2}:\\d{2}:\\d{2}\\s+\\d+\\s)"; + # Pattern for matching pids at start of stderr lines; initially something # that won't match. @@ -407,7 +412,7 @@ RESET_AFTER_EXTRA_LINE_READ: #s/Exim \K\d+[._]\d+[\w_-]*/x.yz/i; # Replace Exim message ids by a unique series - s/((?:[^\W_]{6}-){2}[^\W_]{2}) + s/(\d[^\W_]{5}-[^\W_]{6}-[^\W_]{2}) /new_value($1, "10Hm%s-0005vi-00", \$next_msgid)/egx; # The names of lock files appear in some error and debug messages @@ -461,8 +466,8 @@ RESET_AFTER_EXTRA_LINE_READ: my($date1,$date2,$date3,$expired) = ($1,$2,$3,$4); $expired = '' if !defined $expired; - # Round the time-difference down to nearest even value - my($increment) = ((date_seconds($date3) - date_seconds($date2)) >> 1) << 1; + # Round the time-difference up to nearest even value + my($increment) = ((date_seconds($date3) - date_seconds($date2) + 1) >> 1) << 1; # We used to use globally unique replacement values, but timing # differences make this impossible. Just show the increment on the @@ -598,11 +603,13 @@ RESET_AFTER_EXTRA_LINE_READ: # LibreSSL # TLSv1:AES256-GCM-SHA384:256 # TLSv1:ECDHE-RSA-CHACHA20-POLY1305:256 + # TLS1.3:AEAD-AES256-GCM-SHA384:256 # # ECDHE-RSA-CHACHA20-POLY1305 # AES256-GCM-SHA384 s/(?/ && !/->/ - && !/\*>/ && !/Connection refused/) + && !/\*>/&& !/==/ && !/\*\*/ && !/Connection refused/ && !/in response to/) { s/\[([a-z\d:]+|\d+(?:\.\d+){3})\]:(\d+)/"[".$1."]:".new_value($2,"%s",\$next_port)/ie; } @@ -906,6 +912,9 @@ RESET_AFTER_EXTRA_LINE_READ: s/(TLS error on connection from .* \(SSL_\w+\): error:)(.*)/$1 <>/; next if /SSL verify error: depth=0 error=certificate not trusted/; + # OpenSSL 3.0.0 + s/TLS error \(D-H param setting .* error:\K.*dh key too small/xxxxxxxx:SSL routines::dh key too small/; + # ======== Maildir things ======== # timestamp output in maildir processing s/(timestamp=|\(timestamp_only\): )\d+/$1ddddddd/g; @@ -955,6 +964,9 @@ RESET_AFTER_EXTRA_LINE_READ: # MIME boundaries in RFC3461 DSN messages s/\d{8,10}-eximdsn-\d+/NNNNNNNNNN-eximdsn-MMMMMMMMMM/; + # Cyrus SASL library version differences (rejectlog) + s/Cyrus SASL permanent failure: \Kuser not found$/generic failure/; + # ========================================================== # Some munging is specific to the specific file types @@ -1007,7 +1019,8 @@ RESET_AFTER_EXTRA_LINE_READ: s/conversion: german.xn--strae-oqa.de/conversion: german.straße.de/; # subsecond timstamp info in reported header-files - s/^(-received_time_usec \.)\d{6}$/$1uuuuuu/; + s/^-received_time_usec \.\K\d{6}$/uuuuuu/; + s/^-received_time_complete \K\d+\.\d{6}$/tttt.uuuuuu/; # Postgres server takes varible time to shut down; lives in various places s/^waiting for server to shut down\.+ done$/waiting for server to shut down.... done/; @@ -1019,6 +1032,9 @@ RESET_AFTER_EXTRA_LINE_READ: # ARC is not always supported by the build next if /^arc_sign =/; + # LIMITS is not always supported by the build + next if /^limits_advertise_hosts =/; + # TLS resumption is not always supported by the build next if /^tls_resumption_hosts =/; next if /^-tls_resumption/; @@ -1069,15 +1085,17 @@ RESET_AFTER_EXTRA_LINE_READ: # this is timing-dependent next if /^OpenSSL: creating STEK$/; + next if /^selfsign cert rotate$/; # TLS preload # only OpenSSL speaks of these - next if /^TLS: preloading DH params for server/; + next if /^TLS: (preloading (DH params|ECDH curve|CA bundle) for server|generating selfsigned server cert)/; next if /^Diffie-Hellman initialized from default/; - next if /^TLS: preloading ECDH curve for server/; - next if /^ECDH OpenSSL [< ]?[\d.+]+ temp key parameter settings:/; - next if /^ECDH: .'*prime256v1'/; - next if /^watch dir/; + next if /^ECDH OpenSSL (< )?[\d.+]+: temp key parameter settings:/; + next if /^ECDH: .*'prime256v1'/; + next if /^tls_verify_certificates: system$/; + next if /^tls_set_watch: .*\/cert.pem/; + next if /^Generating 2048 bit RSA key/; # TLS preload # only GnuTLS speaks of these @@ -1086,35 +1104,52 @@ RESET_AFTER_EXTRA_LINE_READ: next if /^TLS: preloading cipher list for server: NULL$/; s/^GnuTLS using default session cipher\/priority "NORMAL"$/TLS: not preloading cipher list for server/; next if /^GnuTLS<2>: added \d+ protocols, \d+ ciphersuites, \d+ sig algos and \d+ groups into priority list$/; + next if /^GnuTLS<2>: (Disabling X.509 extensions|signing structure using RSA-SHA256)/; + next if /^GnuTLS.*(wrap_nettle_mpi_print|gnutls_subject_alt_names_get|get_alt_name)/; + next if /^GnuTLS<[23]>: (p11|ASSERT: pkcs11.c|Initializing needed PKCS #11 modules)/; + next if /^GnuTLS<2>: Intel (AES|GCM) accelerator was detected/; + next if /^Added \d{3} certificate authorities/; + next if /^TLS: not preloading CRL for server/; + next if /^GnuTLS<3>: ASSERT: extensions.c\[_gnutls_get_extension/; + next if /^GnuTLS<3>: ASSERT: \.\.\/\.\.\/\.\.\/lib\/x509\//; + next if /^GnuTLS<2>: Initializing PKCS #11 modules/; + + + # only kevent platforms (FreeBSD, OpenBSD) say this + next if /^watch dir/; + next if /^watch file .*\/usr\/local/; + next if /^watch file .*\/etc\/ssl/; + next if /^closing watch fd:/; # TLS preload # there happen in different orders for OpenSSL/GnuTLS/noTLS + next if /^TLS: generating selfsigned server cert/; next if /^TLS: not preloading (CA bundle|cipher list) for server$/; next if /^TLS: not preloading server certs$/; # drop lookups - next if /^Lookups \(built-in\):/; - next if /^Loading lookup modules from/; - next if /^Loaded \d+ lookup modules/; - next if /^Total \d+ lookups/; + next if /^$time_pid?(?: Lookups\ \(built-in\): + | Loading\ lookup\ modules\ from + | Loaded\ \d+\ lookup\ modules + | Total\ \d+\ lookups)/x; # drop compiler information - next if /^Compiler:/; + next if /^$time_pid?Compiler:/; # and the ugly bit # different libraries will have different numbers (possibly 0) of follow-up # lines, indenting with more data - if (/^Library version:/) { + if (/^$time_pid?Library version:/) { while (1) { $_ = ; - next if /^\s/; + next if /^$time_pid?\s/; goto RESET_AFTER_EXTRA_LINE_READ; } } # drop other build-time controls emitted for debugging - next if /^WHITELIST_D_MACROS:/; - next if /^TRUSTED_CONFIG_LIST:/; + next if /^$time_pid?WHITELIST_D_MACROS:/; + next if /^$time_pid?TRUSTED_CONFIG_LIST:/; # As of Exim 4.74, we log when a setgid fails; because we invoke Exim # with -be, privileges will have been dropped, so this will always @@ -1143,6 +1178,8 @@ RESET_AFTER_EXTRA_LINE_READ: # drop pdkim debugging header next if /^DKIM( <<<<<<<<<<<<<<<<<<<<<<<<<<<<<+|: no signatures)$/; + # Some platforms have TIOCOUTome do not + next if /\d+ bytes remain in socket output buffer$/; # Various other IPv6 lines must be omitted too next if /using host_fake_gethostbyname for \S+ \(IPv6\)/; @@ -1158,14 +1195,16 @@ RESET_AFTER_EXTRA_LINE_READ: next; } - # Non-TLS bulds have a different Recieved: header expansion - s/^((.*)\t}}}}by \$primary_hostname \$\{if def:received_protocol \{with \$received_protocol }})\(Exim \$version_number\)$/$1\${if def:tls_in_cipher_std { tls \$tls_in_cipher_std\n$2\t}}(Exim \$version_number)/; - s/^((\s*).*considering: with \$received_protocol }})\(Exim \$version_number\)$/$1\${if def:tls_in_cipher_std { tls \$tls_in_cipher_std\n$2\t}}(Exim \$version_number)/; - if (/condition: def:tls_in_cipher_std$/) + # Non-TLS builds have a different default Recieved: header expansion + s/^((.*)\t}}}}by \$primary_hostname \$\{if def:received_protocol \{with \$received_protocol }})\(Exim \$version_number\)$/$1\${if def:tls_in_ver { (\$tls_in_ver)}}\${if def:tls_in_cipher_std { tls \$tls_in_cipher_std\n$2\t}}(Exim \$version_number)/; + s/^((\s*).*considering: with \$received_protocol }})\(Exim \$version_number\)$/$1\${if def:tls_in_ver { (\$tls_in_ver)}}\${if def:tls_in_cipher_std { tls \$tls_in_cipher_std\n$2\t}}(Exim \$version_number)/; + if (/condition: def:tls_in_ver$/) { $_= ; $_= ; $_= ; $_= ; $_= ; $_= ; $_= ; $_= ; - $_= ; $_= ; $_= ; next; + $_= ; $_= ; $_= ; $_= ; + $_= ; $_= ; $_= ; $_= ; + $_= ; $_= ; $_= ; $_= ; $_= ; next; } @@ -1257,6 +1296,9 @@ RESET_AFTER_EXTRA_LINE_READ: $_ = $line . $_; } + # Different builds will have different lookup types included + s/^\s*search_type \K\d+ \((\w+)\) quoting -1 \(none\)$/NN ($1) quoting -1 (none)/; + # DISABLE_OCSP next if /in hosts_requ(est|ire)_ocsp\? (no|yes)/; @@ -1272,6 +1314,9 @@ RESET_AFTER_EXTRA_LINE_READ: # Experimental_REQUIRETLS next if / in tls_advertise_requiretls?\? no \(end of list\)/; + # Experimental_LIMITS + next if / in limits_advertise_hosts?\? no \(matched "!\*"\)/; + # TCP Fast Open next if /^(ppppp )?setsockopt FASTOPEN: Network Error/; @@ -1279,7 +1324,7 @@ RESET_AFTER_EXTRA_LINE_READ: next if /\w+ in keep_environment\? (yes|no)/; # Sizes vary with test hostname - s/^cmd buf flush \d+ bytes$/cmd buf flush ddd bytes/; + 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/; @@ -1374,8 +1419,13 @@ RESET_AFTER_EXTRA_LINE_READ: s/^errno = \d+$/errno = EEE/; s/^writing error \d+: /writing error EEE: /; - # Some platforms have to flip to slow-mode taint-checking - next if /switching to slow-mode taint checking/; + # Time-only, in debug output + # we have to handle double lines from the DBOPEN, hence placed down here and /mg + s/^\d\d:\d\d:\d\d\s+/01:01:01 /mg; + + # pid in debug lines + s/^(\d\d:\d\d:\d\d)(\s+\d+\s)/"$1 " . new_value($2, "%s", \$next_pid) . " "/mgxe; + s/(?>/; + s/\(gnutls_handshake\): No common application protocol could be negotiated./(SSL_accept): error: <>/; } # ======== mail ======== @@ -1779,7 +1838,7 @@ if (-e $sf_current) if (-s $mf) { my $sf = /^u/i ? $sf_current : $sf_flavour; - tests_exit(-1, "Failed to cp $mf $sf") if system("cp '$mf' '$sf'") != 0; + copy($mf, $sf) or tests_exit(-1, "Failed to copy $mf $sf"); } else { @@ -1880,11 +1939,6 @@ $munges = { '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/' - }, - 'timeout_errno' => # actual errno differs Solaris vs. Linux { 'mainlog' => 's/((?:host|message) deferral .* errno) <\d+> /$1 /' }, @@ -1985,7 +2039,7 @@ if (! $message_skip) foreach $mail (@mails) { - next if $mail eq "test-mail/oncelog"; + next if $mail =~ /^test-mail\/oncelog(.(dir|pag|db))?$/; $saved_mail = substr($mail, 10); # Remove "test-mail/" $saved_mail =~ s/^$parm_caller(\/|$)/CALLER/; # Convert caller name @@ -2142,7 +2196,7 @@ if ($debug) $prcmd =~ s/; /;\n>> /; print ">> $prcmd\n"; } -system("$cmd"); +system($cmd); } @@ -2266,7 +2320,7 @@ if (/^dump\s+(\S+)/) sort { $a->[0] cmp $b->[0] } #map { [ (split)[0] =~ s/\Q$parm_ipv4/ip4.ip4.ip4.ip4/gr, $_ ] } # this is too modern for 5.10.1 map { - (my $k = (split)[0]) =~ s/\Q$parm_ipv4/ip4.ip4.ip4.ip4/g; + (my $k = (split)[0]) =~ s/\Q$parm_ipv4\E/ip4.ip4.ip4.ip4/g; [ $k, $_ ] } do { local $/ = "\n "; <$in> }; @@ -2287,6 +2341,16 @@ if (/^dump\s+(\S+)/) return $aa cmp $bb; } @temp; } + elsif ($which eq "seen") + { + @temp = sort { + (my $aa = $a) =~ s/^([\d.]+)/$1/; + (my $bb = $b) =~ s/^([\d.]+)/$1/; + $aa =~ s/\Q$parm_ipv4\E/ip4.ip4.ip4.ip4/; + $bb =~ s/\Q$parm_ipv4\E/ip4.ip4.ip4.ip4/; + return $aa cmp $bb; + } @temp; + } print $out @temp; } close($in); # close it explicitly, otherwise $? does not get set @@ -2353,6 +2417,17 @@ if (/^exigrep\s+(.*)/) } +# The "exiqgrep" command runs exiqgrep on the current spool + +if (/^exiqgrep(\s+.*)?/) + { + run_system("(./eximdir/exiqgrep -E ./eximdir/exim -C $parm_cwd/test-config" . ($1 || '') . ";" . + "echo exiqgrep exit code = \$?)" . + ">>test-stdout"); + return 1; + } + + # The "eximstats" command runs eximstats on the current mainlog if (/^eximstats\s+(.*)/) @@ -2925,6 +3000,7 @@ GetOptions( 'valgrind' => \$valgrind, 'range=s{2}' => \my @range_wanted, 'test=i@' => \my @tests_wanted, + 'fail-any!' => \my $fail_any, 'flavor|flavour=s' => \$flavour, 'help' => sub { pod2usage(-exit => 0) }, 'man' => sub { @@ -3033,7 +3109,7 @@ my $eximinfo = "$parm_exim -d -C $parm_cwd/test-config -DDIR=$parm_cwd -bP exim_ chomp(my @eximinfo = `$eximinfo 2>&1`); die "$0: Can't run $eximinfo\n" if $? == -1; -warn 'Got ' . $?>>8 . " from $eximinfo\n" if $?; +warn 'Got ' . ($?>>8) . " from $eximinfo\n" if $?; foreach (@eximinfo) { if (my ($version) = /^Exim version (\S+)/) { @@ -3102,7 +3178,7 @@ if (defined $parm_trusted_config_list) open(TCL, $parm_trusted_config_list) or die "Can't open $parm_trusted_config_list: $!\n"; my $test_config = getcwd() . '/test-config'; die "Can't find '$test_config' in TRUSTED_CONFIG_LIST $parm_trusted_config_list." - if not grep { /^\Q$test_config\E$/ } ; + if not grep { /^\Q$test_config\E$/ } ; } else { @@ -3728,42 +3804,21 @@ system("sudo cp eximdir/exim eximdir/exim_exim;" . ($parm_exim_dir) = $parm_exim =~ m?^(.*)/exim?; $dbm_build_deleted = 0; -if (defined $parm_lookups{dbm} && - system("cp $parm_exim_dir/exim_dbmbuild eximdir") != 0) +if (defined $parm_lookups{dbm} && not cp("$parm_exim_dir/exim_dbmbuild", "eximdir/exim_dbmbuild")) { delete $parm_lookups{dbm}; $dbm_build_deleted = 1; } -if (system("cp $parm_exim_dir/exim_dumpdb eximdir") != 0) - { - tests_exit(-1, "Failed to make a copy of exim_dumpdb: $!"); - } - -if (system("cp $parm_exim_dir/exim_lock eximdir") != 0) - { - tests_exit(-1, "Failed to make a copy of exim_lock: $!"); - } - -if (system("cp $parm_exim_dir/exinext eximdir") != 0) - { - tests_exit(-1, "Failed to make a copy of exinext: $!"); - } - -if (system("cp $parm_exim_dir/exigrep eximdir") != 0) - { - tests_exit(-1, "Failed to make a copy of exigrep: $!"); - } - -if (system("cp $parm_exim_dir/eximstats eximdir") != 0) - { - tests_exit(-1, "Failed to make a copy of eximstats: $!"); - } +foreach my $tool (qw(exim_dumpdb exim_lock exinext exigrep eximstats exiqgrep)) { + cp("$parm_exim_dir/$tool" => "eximdir/$tool") + or tests_exit(-1, "Failed to make a copy of $tool: $!"); +} # Collect some version information print '-' x 78, "\n"; print "Perl version for runtest: $]\n"; -foreach (map { "./eximdir/$_" } qw(exigrep exinext eximstats)) { +foreach (map { "./eximdir/$_" } qw(exigrep exinext eximstats exiqgrep)) { # fold (or unfold?) multiline output into a one-liner print join(', ', map { chomp; $_ } `$_ --version`), "\n"; } @@ -4151,6 +4206,7 @@ if (not $force_continue) { } +my $failures = 0; foreach $test (@test_list) { state $lasttestdir = ''; @@ -4197,15 +4253,15 @@ foreach $test (@test_list) # the test-mail directory for appendfile deliveries. system "sudo /bin/rm -rf spool test-*"; - system "mkdir test-mail 2>/dev/null"; + mkdir "test-mail"; # A privileged Exim will normally make its own spool directory, but some of # the tests run in unprivileged modes that don't always work if the spool # directory isn't already there. What is more, we want anybody to be able # to read it in order to find the daemon's pid. - system "mkdir spool; " . - "sudo chown $parm_eximuser:$parm_eximgroup spool; " . + mkdir "spool"; + system "sudo chown $parm_eximuser:$parm_eximgroup spool; " . "sudo chmod 0755 spool"; # Empty the cache that keeps track of things like message id mappings, and @@ -4384,10 +4440,12 @@ foreach $test (@test_list) print "\nshow stdErr, show stdOut, Retry, Continue (without file comparison), or Quit? [Q] "; $_ = $force_continue ? "c" : ; tests_exit(1) if /^q?$/i; - if (/^c$/ && $force_continue) { - log_failure($log_failed_filename, $testno, "exit code unexpected"); - log_test($log_summary_filename, $testno, 'F') - } + if (/^c$/ && $force_continue) + { + log_failure($log_failed_filename, $testno, "exit code unexpected"); + log_test($log_summary_filename, $testno, 'F'); + $failures++; + } if ($force_continue) { print "\nstdout tail:\n"; @@ -4440,7 +4498,7 @@ foreach $test (@test_list) { if (($? & 0xff) == 0) { printf("Server return code %d for test %d starting line %d", $?/256, - $testno, $subtest_startline); } + $testno, $subtest_startline); } elsif (($? & 0xff00) == 0) { printf("Server killed by signal %d", $? & 255); } else @@ -4451,10 +4509,12 @@ foreach $test (@test_list) print "\nShow server stdout, Retry, Continue, or Quit? [Q] "; $_ = $force_continue ? "c" : ; tests_exit(1) if /^q?$/i; - if (/^c$/ && $force_continue) { - log_failure($log_failed_filename, $testno, "exit code unexpected"); - log_test($log_summary_filename, $testno, 'F') - } + if (/^c$/ && $force_continue) + { + log_failure($log_failed_filename, $testno, "exit code unexpected"); + log_test($log_summary_filename, $testno, 'F'); + $failures++; + } print "... continue forced\n" if $force_continue; last if /^[rc]$/i; @@ -4489,7 +4549,14 @@ foreach $test (@test_list) { sleep 1 if $slow; my $rc = check_output($TEST_STATE->{munge}); - log_test($log_summary_filename, $testno, 'P') if ($rc == 0); + if ($rc == 0) + { + log_test($log_summary_filename, $testno, 'P'); + } + else + { + $failures++; + } if ($rc < 2) { print (" Script completed\n"); @@ -4508,7 +4575,7 @@ foreach $test (@test_list) ################################################## tests_exit(-1, "No runnable tests selected") if not @test_list; -tests_exit(0); +tests_exit($fail_any ? $failures : 0); __END__