DKIM: fix simple body verify for trailing empty lines after text
[exim.git] / test / runtest
index 7fc658a204c82082ff8f9ca3abe51f7133dd8266..3b0c6bbf064890b99b23bec58a596df4fb9d8065 100755 (executable)
@@ -20,6 +20,7 @@ use Socket;
 use Time::Local;
 use Cwd;
 use File::Basename;
+use if $ENV{DEBUG} && $ENV{DEBUG} =~ /\bruntest\b/ => ('Smart::Comments' => '####');
 
 
 # Start by initializing some global variables
@@ -82,6 +83,10 @@ $parm_port_d4 = 1228;        # Additional for daemon
 # Manually set locale
 $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};
 
 
 ###############################################################################
@@ -322,6 +327,8 @@ my($extra) = $_[1];
 my($yield) = 0;
 my(@saved) = ();
 
+local $_;
+
 open(IN, "$file") || tests_exit(-1, "Failed to open $file: $!");
 
 my($is_log) = $file =~ /log/;
@@ -867,7 +874,7 @@ RESET_AFTER_EXTRA_LINE_READ:
     # IP address lookups use gethostbyname() when IPv6 is not supported,
     # and gethostbyname2() or getipnodebyname() when it is.
 
-    s/\bgethostbyname2?|\bgetipnodebyname/get[host|ipnode]byname[2]/;
+    s/\b(gethostbyname2?|\bgetipnodebyname)(\(af=inet\))?/get[host|ipnode]byname[2]/;
 
     # drop gnutls version strings
     next if /GnuTLS compile-time version: \d+[\.\d]+$/;
@@ -945,7 +952,7 @@ RESET_AFTER_EXTRA_LINE_READ:
     # 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.
 
@@ -1011,6 +1018,9 @@ 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.
 
@@ -1069,7 +1079,7 @@ return $yield;
 # Arguments: [0] the prompt string
 #            [1] if there is a U in the prompt and $force_update is true
 #            [2] if there is a C in the prompt and $force_continue is true
-# Returns:   nothing (it sets $_)
+# Returns:   returns the answer
 
 sub interact{
 print $_[0];
@@ -1178,6 +1188,8 @@ if (! -e $sf_current)
     }
   }
 
+#### $_
+
 # Control reaches here if either (a) there is a saved file ($sf), or (b) there
 # was a request to create a saved file. First, create the munged file from any
 # data that does exist.
@@ -1350,9 +1362,6 @@ $munges =
     'optional_ocsp' =>
     { 'stderr' => '/127.0.0.1 in hosts_requ(ire|est)_ocsp/' },
 
-    'no_tpt_filter_epipe' =>
-    { 'stderr' => '/^writing error 32: Broken pipe$/' },
-
     'optional_cert_hostnames' =>
     { 'stderr' => '/in tls_verify_cert_hostnames\? no/' },
 
@@ -1362,6 +1371,22 @@ $munges =
     'scanfile_size' =>
     { 'stdout' => 's/(Content-length:) \d\d\d/$1 ddd/' },
 
+    'delay_1500' =>
+    { 'stderr' => 's/(1[5-9]|23\d)\d\d msec/ssss msec/' },
+
+    'tls_anycipher' =>
+    { 'mainlog' => 's/ X=TLS\S+ / X=TLS_proto_and_cipher /' },
+
+    'debug_pid' =>
+    { 'stderr' => 's/(^\s{0,4}|(?<=Process )|(?<=child ))\d{1,5}/ppppp/g' },
+
+    'optional_dsn_info' =>
+    { 'mail' => '/^(X-(Remote-MTA-(smtp-greeting|helo-response)|Exim-Diagnostic|(body|message)-linecount):|Remote-MTA: X-ip;)/'
+    },
+
+    'sys_bindir' =>
+    { 'mainlog' => 's%/(usr/)?bin/%SYSBINDIR/%' },
+
   };
 
 
@@ -1926,7 +1951,8 @@ if (/^(ln|ls|du|mkdir|mkfifo|touch|cp|cat)\s/ ||
 
 if (/^server\s+(.*)$/)
   {
-  $cmd = "./bin/server $server_opts $1 >>test-stdout-server";
+  $pidfile = "$parm_cwd/aux-var/server-daemon.pid";
+  $cmd = "./bin/server $server_opts -oP $pidfile $1 >>test-stdout-server";
   print ">> $cmd\n" if ($debug);
   $server_pid = open SERVERCMD, "|$cmd" || tests_exit(-1, "Failed to run $cmd");
   SERVERCMD->autoflush(1);
@@ -1940,10 +1966,9 @@ if (/^server\s+(.*)$/)
   print SERVERCMD "++++\n"; # Send end to server; can't send EOF yet
                             # because close() waits for the process.
 
-  # This gives the server time to get started; otherwise the next
+  # Interlock the server startup; otherwise the next
   # process may not find it there when it expects it.
-
-  select(undef, undef, undef, 0.5);
+  while (! stat("$pidfile") ) { select(undef, undef, undef, 0.3); }
   return 3;
   }
 
@@ -2040,12 +2065,12 @@ 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+)?exim(_\S+)?\s+(.*)$/)
+elsif (/^([A-Z_]+=\S+\s+)?(\d+)?\s*(sudo(?:\s+-u\s+(\w+))?\s+)?exim(_\S+)?\s+(.*)$/)
   {
-  $args = $5;
+  $args = $6;
   my($envset) = (defined $1)? $1      : "";
-  my($sudo)   = (defined $3)? "sudo " : "";
-  my($special)= (defined $4)? $4      : "";
+  my($sudo)   = (defined $3)? "sudo " . (defined $4 ? "-u $4 ":"")  : "";
+  my($special)= (defined $5)? $5      : "";
   $wait_time  = (defined $2)? $2      : 0;
 
   # Return 2 rather than 1 afterwards
@@ -2105,7 +2130,6 @@ elsif (/^([A-Z_]+=\S+\s+)?(\d+)?\s*(sudo\s+)?exim(_\S+)?\s+(.*)$/)
          "-DEXIM_PATH=$parm_cwd/eximdir/exim$special " .
          "-C $parm_cwd/test-config $args " .
          ">>test-stdout 2>>test-stderr";
-
   # If the command is starting an Exim daemon, we run it in the same
   # way as the "server" command above, that is, we don't want to wait
   # for the process to finish. That happens when "killdaemon" is obeyed later
@@ -2119,6 +2143,7 @@ elsif (/^([A-Z_]+=\S+\s+)?(\d+)?\s*(sudo\s+)?exim(_\S+)?\s+(.*)$/)
 
   if ($cmd =~ /\s-DSERVER=server\s/ && $cmd !~ /\s-DNOTDAEMON\s/)
     {
+    $pidfile = "$parm_cwd/spool/exim-daemon.pid";
     if ($debug) { printf ">> daemon: $cmd\n"; }
     run_system("sudo mkdir spool/log 2>/dev/null");
     run_system("sudo chown $parm_eximuser:$parm_eximgroup spool/log");
@@ -2129,12 +2154,23 @@ elsif (/^([A-Z_]+=\S+\s+)?(\d+)?\s*(sudo\s+)?exim(_\S+)?\s+(.*)$/)
     # file is written to the spool directory, in case the Exim binary was
     # built with PID_FILE_PATH pointing somewhere else.
 
-    $cmd =~ s!\s-bd\s! -bdf -oP $parm_cwd/spool/exim-daemon.pid !;
+    if ($cmd =~ /\s-oP\s/)
+      {
+      ($pidfile = $cmd) =~ s/^.*-oP ([^ ]+).*$/$1/;
+      $cmd =~ s!\s-bd\s! -bdf !;
+      }
+    else
+      {
+      $pidfile = "$parm_cwd/spool/exim-daemon.pid";
+      $cmd =~ s!\s-bd\s! -bdf -oP $pidfile !;
+      }
     print ">> |${cmd}-server\n" if ($debug);
     open DAEMONCMD, "|${cmd}-server" || tests_exit(-1, "Failed to run $cmd");
     DAEMONCMD->autoflush(1);
     while (<SCRIPT>) { $lineno++; last if /^\*{4}\s*$/; }   # Ignore any input
-    select(undef, undef, undef, 0.3);             # Let the daemon get going
+
+    # Interlock with daemon startup
+    while (! stat("$pidfile") ) { select(undef, undef, undef, 0.3); }
     return 3;                                     # Don't wait
     }
   elsif ($cmd =~ /\s-DSERVER=wait:(\d+)\s/)
@@ -2359,7 +2395,7 @@ if ($parm_exim eq "")
     # directory. Thus, we should choose the highest version of Exim that has
     # been compiled.
 
-    if ($f eq "exim4" || $f eq "exim-snapshot")
+    if ($f eq "exim4" || $f eq "exim-snapshot" || $f eq 'src')
       { $srcdir = $f; }
     else
       { $srcdir = $f
@@ -2425,8 +2461,13 @@ if ($parm_exim eq "")
 
 # 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 " .
@@ -2883,7 +2924,7 @@ while (($parm_ipv4 eq "" || $parm_ipv6 eq "") && ($_ = <IFCONFIG>))
       $_ =~ /^\s*inet(?:\saddr)?:?\s?(\d+\.\d+\.\d+\.\d+)\s/i)
     {
     $ip = $1;
-    next if ($ip =~ /^127\./);
+    next if ($ip =~ /^127\./ || $ip =~ /^10\./);
     $parm_ipv4 = $ip;
     }
 
@@ -3591,6 +3632,8 @@ foreach $test (@test_list)
     my($rc, $run_extra) = run_command($testno, \$subtestno, \$expectrc, \$commandname, $TEST_STATE);
     my($cmdrc) = $?;
 
+$0 = "[runtest $testno]";
+
     if ($debug) {
       print ">> rc=$rc cmdrc=$cmdrc\n";
       if (defined $run_extra) {
@@ -3703,6 +3746,7 @@ foreach $test (@test_list)
 
   # The script has finished. Check the all the output that was generated. The
   # function returns 0 if all is well, 1 if we should rerun the test (the files
+  # function returns 0 if all is well, 1 if we should rerun the test (the files
   # have been updated). It does not return if the user responds Q to a prompt.
 
   if ($retry)