nicer retry message
[users/heiko/exim.git] / test / runtest
index 7af30763b86e5f48e86ce6c0b5d1e320971fbb93..4843fa80ed7ade61fb1b15bd5f059e4f357f35f4 100755 (executable)
@@ -38,6 +38,7 @@ $gnutls_dh_bits_normal = 2236;
 $cf = "bin/cf -exact";
 $cr = "\r";
 $debug = 0;
 $cf = "bin/cf -exact";
 $cr = "\r";
 $debug = 0;
+$flavour = 'FOO';
 $force_continue = 0;
 $force_update = 0;
 $log_failed_filename = "failed-summary.log";
 $force_continue = 0;
 $force_update = 0;
 $log_failed_filename = "failed-summary.log";
@@ -45,7 +46,7 @@ $more = "less -XF";
 $optargs = "";
 $save_output = 0;
 $server_opts = "";
 $optargs = "";
 $save_output = 0;
 $server_opts = "";
-$flavour = 'FOO';
+$valgrind = 0;
 
 $have_ipv4 = 1;
 $have_ipv6 = 1;
 
 $have_ipv4 = 1;
 $have_ipv6 = 1;
@@ -348,7 +349,7 @@ $spid = "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx";
 # that are specific to certain file types, though there are also some of those
 # inline too.
 
 # that are specific to certain file types, though there are also some of those
 # inline too.
 
-while(<IN>)
+LINE: while(<IN>)
   {
 RESET_AFTER_EXTRA_LINE_READ:
   # Custom munges
   {
 RESET_AFTER_EXTRA_LINE_READ:
   # Custom munges
@@ -563,6 +564,25 @@ RESET_AFTER_EXTRA_LINE_READ:
   # signature algorithm names
   s/RSA-SHA1/RSA-SHA/;
 
   # signature algorithm names
   s/RSA-SHA1/RSA-SHA/;
 
+  # -d produces a list of environment variables as they are checked if they exist
+  # in the environment. Unfortunately this list isn't always in the same order. For now we
+  # just remove this list
+  #
+  if (/^\w+ in keep_environment/)
+    {
+    my @lines = $_;
+    while (<IN>)
+      {
+      if (/^\w+ in keep_environment/)
+        {
+        push @lines, $_;
+        next;
+        }
+      print MUNGED sort grep { !/^(SHLVL|_) / } @lines;
+      redo LINE;
+      }
+    }
+
 
   # ======== Caller's login, uid, gid, home, gecos ========
 
 
   # ======== Caller's login, uid, gid, home, gecos ========
 
@@ -771,6 +791,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 <<detail omitted>>/;
   # different wording in the error messages, so we cannot compare them.
 
   s/(TLS error on connection (?:from .* )?\(SSL_\w+\): error:)(.*)/$1 <<detail omitted>>/;
+  next if /SSL verify error: depth=0 error=certificate not trusted/;
 
   # ======== Maildir things ========
   # timestamp output in maildir processing
 
   # ======== Maildir things ========
   # timestamp output in maildir processing
@@ -857,6 +878,11 @@ RESET_AFTER_EXTRA_LINE_READ:
     next if /^SSL info: unknown state/;
     next if /^SSL info: SSLv2\/v3 write client hello A/;
     next if /^SSL info: SSLv3 read server key exchange A/;
     next if /^SSL info: unknown state/;
     next if /^SSL info: SSLv2\/v3 write client hello A/;
     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 ========
     }
 
   # ======== stderr ========
@@ -952,7 +978,7 @@ RESET_AFTER_EXTRA_LINE_READ:
     # are unset, because tls ain't always there.
 
     next if /in\s(?:tls_advertise_hosts\?|hosts_require_tls\?)
     # are unset, because tls ain't always there.
 
     next if /in\s(?:tls_advertise_hosts\?|hosts_require_tls\?)
-                \sno\s\(option\sunset\)/x;
+                \sno\s\((option\sunset|end\sof\slist)\)/x;
 
     # Skip auxiliary group lists because they will vary.
 
 
     # Skip auxiliary group lists because they will vary.
 
@@ -1026,6 +1052,9 @@ RESET_AFTER_EXTRA_LINE_READ:
 
     next if /in\shosts_require_dane\?\sno\s\(option\sunset\)/x;
 
 
     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\)/;
 
     # Experimental_International
     next if / in smtputf8_advertise_hosts\? no \(option unset\)/;
 
@@ -1382,7 +1411,24 @@ $munges =
 
     'optional_dsn_info' =>
     { 'mail' => '/^(X-(Remote-MTA-(smtp-greeting|helo-response)|Exim-Diagnostic|(body|message)-linecount):|Remote-MTA: X-ip;)/'
 
     'optional_dsn_info' =>
     { '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<suppressed>/',
+      'rejectlog' => 's/^(.* SMTP protocol synchronization error .* next input=.{8}).*$/$1<suppressed>/'},
 
   };
 
 
   };
 
@@ -1659,6 +1705,8 @@ my($commandnameref) = $_[3];
 my($aux_info) = $_[4];
 my($yield) = 1;
 
 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];
 if (/^(\d+)\s*$/)                # Handle unusual return code
   {
   my($r) = $_[2];
@@ -1924,7 +1972,7 @@ if (/^sleep\s+(.*)$/)
 # Various Unix management commands are recognized
 
 if (/^(ln|ls|du|mkdir|mkfifo|touch|cp|cat)\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|chown|chmod)\s/)
   {
   run_system("$_ >>test-stdout 2>>test-stderr");
   return 1;
   {
   run_system("$_ >>test-stdout 2>>test-stderr");
   return 1;
@@ -2062,7 +2110,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.
 
 # 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      : "";
   {
   $args = $6;
   my($envset) = (defined $1)? $1      : "";
@@ -2123,7 +2171,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/;
 
 
   $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";
          "-DEXIM_PATH=$parm_cwd/eximdir/exim$special " .
          "-C $parm_cwd/test-config $args " .
          ">>test-stdout 2>>test-stderr";
@@ -2204,6 +2255,45 @@ elsif (/^([A-Z_]+=\S+\s+)?(\d+)?\s*(sudo(?:\s+-u\s+(\w+))?\s+)?exim(_\S+)?\s+(.*
     }
   }
 
     }
   }
 
+# The "background" command is run but not waited-for, like exim -DSERVER=server.
+# One script line is read and fork-exec'd.  The PID is stored for a later
+# killdaemon.
+
+elsif (/^background$/)
+  {
+  my $line;
+#  $pidfile = "$parm_cwd/aux-var/server-daemon.pid";
+
+  $_ = <SCRIPT>; $lineno++;
+  chomp;
+  $line = $_;
+  if ($debug) { printf ">> daemon: $line >>test-stdout 2>>test-stderr\n"; }
+
+  my $pid = fork();
+  if (not defined $pid) { die "** fork failed: $!\n" }
+  if (not $pid) {
+    print "[$$]>> ${line}\n" if ($debug);
+    close(STDIN);
+    open(STDIN, "<", "test-stdout");
+    close(STDOUT);
+    open(STDOUT, ">>", "test-stdout");
+    close(STDERR);
+    open(STDERR, ">>", "test-stderr-server");
+    exec "exec ${line}";
+    exit(1);
+  }
+
+#  open(my $fh, ">", $pidfile) ||
+#      tests_exit(-1, "Failed to open $pidfile: $!");
+#  printf($fh, "%d\n", $pid);
+#  close($fh);
+
+  while (<SCRIPT>) { $lineno++; last if /^\*{4}\s*$/; }   # Ignore any input
+  select(undef, undef, undef, 0.3);             # Let the daemon get going
+  return (3, { exim_pid => $pid });             # Don't wait
+  }
+
+
 
 # Unknown command
 
 
 # Unknown command
 
@@ -2339,6 +2429,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 "-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";
     if ($arg =~ /^-FLAVOU?R$/) { $flavour = shift; next; }
     }
   $optargs .= " $arg";
@@ -2458,8 +2549,13 @@ if ($parm_exim eq "")
 
 # deal with TRUSTED_CONFIG_LIST restrictions
 unlink("$parm_cwd/test-config") if -e "$parm_cwd/test-config";
 
 # deal with TRUSTED_CONFIG_LIST restrictions
 unlink("$parm_cwd/test-config") if -e "$parm_cwd/test-config";
-symlink("$parm_cwd/confs/0000", "$parm_cwd/test-config")
-  or die "Unable to link initial config into place: $!\n";
+open (IN, "$parm_cwd/confs/0000") ||
+  tests_exit(-1, "Couldn't open $parm_cwd/confs/0000: $!\n");
+open (OUT, ">test-config") ||
+  tests_exit(-1, "Couldn't open test-config: $!\n");
+while (<IN>) { print OUT; }
+close(IN);
+close(OUT);
 
 print("Probing with config file: $parm_cwd/test-config\n");
 open(EXIMINFO, "$parm_exim -d -C $parm_cwd/test-config -DDIR=$parm_cwd " .
 
 print("Probing with config file: $parm_cwd/test-config\n");
 open(EXIMINFO, "$parm_exim -d -C $parm_cwd/test-config -DDIR=$parm_cwd " .
@@ -2470,6 +2566,7 @@ while(<EXIMINFO>)
   $parm_eximuser = $1 if /^exim_user = (.*)$/;
   $parm_eximgroup = $1 if /^exim_group = (.*)$/;
   $parm_trusted_config_list = $1 if /^TRUSTED_CONFIG_LIST:.*?"(.*?)"$/;
   $parm_eximuser = $1 if /^exim_user = (.*)$/;
   $parm_eximgroup = $1 if /^exim_group = (.*)$/;
   $parm_trusted_config_list = $1 if /^TRUSTED_CONFIG_LIST:.*?"(.*?)"$/;
+  print "$_" if /wrong owner/;
   }
 close(EXIMINFO);
 
   }
 close(EXIMINFO);
 
@@ -2520,7 +2617,7 @@ else
   die "Unable to check the TRUSTED_CONFIG_LIST, seems to be empty?\n";
   }
 
   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 |") ||
+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";
   die "** Cannot run $parm_exim: $!\n";
 
 print "-" x 78, "\n";
@@ -2529,7 +2626,7 @@ while (<EXIMINFO>)
   {
   my(@temp);
 
   {
   my(@temp);
 
-  if (/^Exim version/) { print; }
+  if (/^(Exim|Library) version/) { print; }
 
   elsif (/^Size of off_t: (\d+)/)
     {
 
   elsif (/^Size of off_t: (\d+)/)
     {
@@ -2798,6 +2895,22 @@ if (defined $parm_support{'Content_Scanning'})
   }
 
 
   }
 
 
+##################################################
+#       Check for redis                          #
+##################################################
+if (defined $parm_lookups{'redis'})
+  {
+  if (system("redis-server -v 2>/dev/null >/dev/null") == 0)
+    {
+    print "The redis-server command works\n";
+    $parm_running{'redis'} = ' ';
+    }
+  else
+    {
+    print "The redis-server command failed: assume Redis not installed\n";
+    }
+  }
+
 ##################################################
 #         Test for the basic requirements        #
 ##################################################
 ##################################################
 #         Test for the basic requirements        #
 ##################################################
@@ -3132,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)");
 }
   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 ...";
 
 
 print "The Exim user needs access to the test suite directory. Checking ...";
 
@@ -3615,8 +3733,9 @@ foreach $test (@test_list)
 
     my($subtest_startline) = $lineno;
 
 
     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) = "";
     # was run and not waited for (usually a daemon or server startup).
 
     my($commandname) = "";
@@ -3679,7 +3798,15 @@ $0 = "[runtest $testno]";
         $_ = $force_continue ? "c" : <T>;
         tests_exit(1) if /^q?$/i;
         log_failure($log_failed_filename, $testno, "exit code unexpected") if (/^c$/i && $force_continue);
         $_ = $force_continue ? "c" : <T>;
         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)
           {
         last if /^[rc]$/i;
         if (/^e$/i)
           {