Testsuite: add support for relative name of exim
[users/jgh/exim.git] / test / runtest
index 8435fccfcf5691b4b0fe3ccfa988a1026dfbcd40..249c7cf59db30d5d4474d591d6dba2f84ef38444 100755 (executable)
@@ -413,6 +413,7 @@ RESET_AFTER_EXTRA_LINE_READ:
 
   # Random local part in callout cache testing
   s/myhost.test.ex-\d+-testing/myhost.test.ex-dddddddd-testing/;
 
   # Random local part in callout cache testing
   s/myhost.test.ex-\d+-testing/myhost.test.ex-dddddddd-testing/;
+  s/the.local.host.name-\d+-testing/the.local.host.name-dddddddd-testing/;
 
   # File descriptor numbers may vary
   s/^writing data block fd=\d+/writing data block fd=dddd/;
 
   # File descriptor numbers may vary
   s/^writing data block fd=\d+/writing data block fd=dddd/;
@@ -491,6 +492,9 @@ RESET_AFTER_EXTRA_LINE_READ:
   s/Exim\sstatistics\sfrom\s\d{4}-\d\d-\d\d\s\d\d:\d\d:\d\d\sto\s
     \d{4}-\d\d-\d\d\s\d\d:\d\d:\d\d/Exim statistics from <time> to <time>/x;
 
   s/Exim\sstatistics\sfrom\s\d{4}-\d\d-\d\d\s\d\d:\d\d:\d\d\sto\s
     \d{4}-\d\d-\d\d\s\d\d:\d\d:\d\d/Exim statistics from <time> to <time>/x;
 
+  # Treat ECONNRESET the same as ECONNREFUSED.  At least some systems give
+  # us the former on a new connection.
+  s/(could not connect to .*: Connection) reset by peer$/$1 refused/;
 
   # ======== TLS certificate algorithms ========
   # Test machines might have various different TLS library versions supporting
 
   # ======== TLS certificate algorithms ========
   # Test machines might have various different TLS library versions supporting
@@ -700,6 +704,9 @@ RESET_AFTER_EXTRA_LINE_READ:
   # ======== Other error numbers ========
   s/errno=\d+/errno=dd/g;
 
   # ======== Other error numbers ========
   s/errno=\d+/errno=dd/g;
 
+  # ======== System Error Messages ======
+  # depending on the underlaying file system the error message seems to differ
+  s/(?: is not a regular file)|(?: has too many links \(\d+\))/ not a regular file or too many links/;
 
   # ======== Output from ls ========
   # Different operating systems use different spacing on long output
 
   # ======== Output from ls ========
   # Different operating systems use different spacing on long output
@@ -728,8 +735,8 @@ RESET_AFTER_EXTRA_LINE_READ:
   s/this message = \d+\b/this message = sss/;
   s/Size of headers = \d+/Size of headers = sss/;
   s/sum=(?!0)\d+/sum=dddd/;
   s/this message = \d+\b/this message = sss/;
   s/Size of headers = \d+/Size of headers = sss/;
   s/sum=(?!0)\d+/sum=dddd/;
-  s/(?<=sum=dddd )count=(?!0)\d+\b/count=dd/;
-  s/(?<=sum=0 )count=(?!0)\d+\b/count=dd/;
+  s/(?<=sum=dddd )count=\d+\b/count=dd/;
+  s/(?<=sum=0 )count=\d+\b/count=dd/;
   s/,S is \d+\b/,S is ddddd/;
   s/\+0100,\d+;/+0100,ddd;/;
   s/\(\d+ bytes written\)/(ddd bytes written)/;
   s/,S is \d+\b/,S is ddddd/;
   s/\+0100,\d+;/+0100,ddd;/;
   s/\(\d+ bytes written\)/(ddd bytes written)/;
@@ -806,7 +813,7 @@ RESET_AFTER_EXTRA_LINE_READ:
 
   # ==========================================================
   # MIME boundaries in RFC3461 DSN messages
 
   # ==========================================================
   # MIME boundaries in RFC3461 DSN messages
-  s/\d{8,10}-eximdsn-\d{8,10}/NNNNNNNNNN-eximdsn-MMMMMMMMMM/;
+  s/\d{8,10}-eximdsn-\d+/NNNNNNNNNN-eximdsn-MMMMMMMMMM/;
 
   # ==========================================================
   # Some munging is specific to the specific file types
 
   # ==========================================================
   # Some munging is specific to the specific file types
@@ -841,7 +848,6 @@ 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/;
-
     }
 
   # ======== stderr ========
     }
 
   # ======== stderr ========
@@ -896,7 +902,7 @@ RESET_AFTER_EXTRA_LINE_READ:
     # 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
     # be the case
     # 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
     # be the case
-    next if /^changing group to \d+ failed: Operation not permitted/;
+    next if /^changing group to \d+ failed: (Operation not permitted|Not owner)/;
 
     # We might not keep this check; rather than change all the tests, just
     # ignore it as long as it succeeds; then we only need to change the
 
     # We might not keep this check; rather than change all the tests, just
     # ignore it as long as it succeeds; then we only need to change the
@@ -1008,6 +1014,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;
 
+    # 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.
 
       # Skip some lines that Exim puts out at the start of debugging output
       # because they will be different in different binaries.
 
@@ -1024,11 +1033,21 @@ RESET_AFTER_EXTRA_LINE_READ:
                 /^Fixed never_users:/ ||
                 /^Size of off_t:/
                 );
                 /^Fixed never_users:/ ||
                 /^Size of off_t:/
                 );
+
+
       }
 
     next;
     }
 
       }
 
     next;
     }
 
+  # ======== log ========
+
+  elsif ($is_log)
+    {
+    # Berkeley DB version differences
+    next if / Berkeley DB error: /;
+    }
+
   # ======== All files other than stderr ========
 
   print MUNGED;
   # ======== All files other than stderr ========
 
   print MUNGED;
@@ -1294,19 +1313,31 @@ return 1;
 ##################################################
 $munges =
   { 'dnssec' =>
 ##################################################
 $munges =
   { 'dnssec' =>
-    { 'stderr' => '/^Reverse DNS security status: unverified\n/', },
+    { 'stderr' => '/^Reverse DNS security status: unverified\n/' },
 
     'gnutls_unexpected' =>
 
     'gnutls_unexpected' =>
-    { 'mainlog' => '/\(recv\): A TLS packet with unexpected length was received./', },
+    { 'mainlog' => '/\(recv\): A TLS packet with unexpected length was received./' },
 
     'gnutls_handshake' =>
 
     'gnutls_handshake' =>
-    { 'mainlog' => 's/\(gnutls_handshake\): Error in the push function/\(gnutls_handshake\): A TLS packet with unexpected length was received/', },
+    { 'mainlog' => 's/\(gnutls_handshake\): Error in the push function/\(gnutls_handshake\): A TLS packet with unexpected length was received/' },
 
     'optional_events' =>
 
     'optional_events' =>
-    { 'stdout' => '/event_action =/', },
+    { 'stdout' => '/event_action =/' },
 
     'optional_ocsp' =>
 
     'optional_ocsp' =>
-    { 'stderr' => '/127.0.0.1 in hosts_requ(ire|est)_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/' },
+
+    'loopback' =>
+    { 'stdout' => 's/[[](127\.0\.0\.1|::1)]/[IP_LOOPBACK_ADDR]/' },
+
+    'scanfile_size' =>
+    { 'stdout' => 's/(Content-length:) \d\d\d/$1 ddd/' },
 
   };
 
 
   };
 
@@ -1325,7 +1356,7 @@ $munges =
 #  [4] TRUE if this is a log file whose deliveries must be sorted
 #  [5] an optional custom munge command
 #
 #  [4] TRUE if this is a log file whose deliveries must be sorted
 #  [5] an optional custom munge command
 #
-# Arguments: Optionally, name of a custom munge to run.
+# Arguments: Optionally, name of a single custom munge to run.
 # Returns:   0 if the output compared equal
 #            1 if re-run needed (files may have been updated)
 
 # Returns:   0 if the output compared equal
 #            1 if re-run needed (files may have been updated)
 
@@ -1652,19 +1683,42 @@ if (/^dump\s+(\S+)/)
   my(@temp);
   print ">> ./eximdir/exim_dumpdb $parm_cwd/spool $which\n" if $debug;
   open(IN, "./eximdir/exim_dumpdb $parm_cwd/spool $which |");
   my(@temp);
   print ">> ./eximdir/exim_dumpdb $parm_cwd/spool $which\n" if $debug;
   open(IN, "./eximdir/exim_dumpdb $parm_cwd/spool $which |");
-  @temp = <IN>;
-  close(IN);
-  if ($which eq "callout")
+  open(OUT, ">>test-stdout");
+  print OUT "+++++++++++++++++++++++++++\n";
+
+  if ($which eq "retry")
     {
     {
+    $/ = "\n  ";
+    @temp = <IN>;
+    $/ = "\n";
+
     @temp = sort {
     @temp = sort {
-                 my($aa) = substr $a, 21;
-                 my($bb) = substr $b, 21;
-                 return $aa cmp $bb;
+                   my($aa) = split(' ', $a);
+                   my($bb) = split(' ', $b);
+                   return $aa cmp $bb;
                  } @temp;
                  } @temp;
+
+    foreach $item (@temp)
+      {
+      $item =~ s/^\s*(.*)\n(.*)\n?\s*$/$1\n$2/m;
+      print OUT "  $item\n";
+      }
     }
     }
-  open(OUT, ">>test-stdout");
-  print OUT "+++++++++++++++++++++++++++\n";
-  print OUT @temp;
+  else
+    {
+    @temp = <IN>;
+    if ($which eq "callout")
+      {
+      @temp = sort {
+                   my($aa) = substr $a, 21;
+                   my($bb) = substr $b, 21;
+                   return $aa cmp $bb;
+                   } @temp;
+      }
+    print OUT @temp;
+    }
+
+  close(IN);
   close(OUT);
   return 1;
   }
   close(OUT);
   return 1;
   }
@@ -2153,6 +2207,15 @@ return $yield;            # Ran command and waited
 autoflush STDOUT 1;
 print "Exim tester $testversion\n";
 
 autoflush STDOUT 1;
 print "Exim tester $testversion\n";
 
+# extend the PATH with .../sbin
+# we map all (.../bin) to (.../sbin:.../bin)
+$ENV{PATH} = do {
+  my %seen = map { $_, 1 } split /:/, $ENV{PATH};
+  join ':' => map { m{(.*)/bin$} 
+                ? ( $seen{"$1/sbin"} ? () : ("$1/sbin"), $_) 
+                : ($_) } 
+      split /:/, $ENV{PATH};
+};
 
 ##################################################
 #      Some tests check created file modes       #
 
 ##################################################
 #      Some tests check created file modes       #
@@ -2190,9 +2253,10 @@ else
 ##################################################
 
 # If the first character of the first argument is '/', the argument is taken
 ##################################################
 
 # If the first character of the first argument is '/', the argument is taken
-# as the path to the binary.
+# as the path to the binary. If the first argument does not start with a
+# '/' but exists in the file system, it's assumed to be the Exim binary.
 
 
-$parm_exim = (@ARGV > 0 && $ARGV[0] =~ m?^/?)? shift @ARGV : "";
+$parm_exim = (@ARGV > 0 && (-x $ARGV[0] or $ARGV[0] =~ m?^/?))? Cwd::abs_path(shift @ARGV) : "";
 print "Exim binary is $parm_exim\n" if $parm_exim ne "";
 
 
 print "Exim binary is $parm_exim\n" if $parm_exim ne "";
 
 
@@ -2342,12 +2406,13 @@ symlink("$parm_cwd/confs/0000", "$parm_cwd/test-config")
 
 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 " .
-               "-bP exim_user exim_group|") ||
+               "-bP exim_user exim_group 2>&1|") ||
   die "** Cannot run $parm_exim: $!\n";
 while(<EXIMINFO>)
   {
   $parm_eximuser = $1 if /^exim_user = (.*)$/;
   $parm_eximgroup = $1 if /^exim_group = (.*)$/;
   die "** Cannot run $parm_exim: $!\n";
 while(<EXIMINFO>)
   {
   $parm_eximuser = $1 if /^exim_user = (.*)$/;
   $parm_eximgroup = $1 if /^exim_group = (.*)$/;
+  $parm_trusted_config_list = $1 if /^TRUSTED_CONFIG_LIST:.*?"(.*?)"$/;
   }
 close(EXIMINFO);
 
   }
 close(EXIMINFO);
 
@@ -2370,6 +2435,34 @@ if (defined $parm_eximgroup)
     else { $parm_exim_gid = getgrnam($parm_eximgroup); }
   }
 
     else { $parm_exim_gid = getgrnam($parm_eximgroup); }
   }
 
+# check the permissions on the TRUSTED_CONFIG_LIST
+if (defined $parm_trusted_config_list)
+  {
+  die "TRUSTED_CONFIG_LIST: $parm_trusted_config_list: $!\n"
+    if not -f $parm_trusted_config_list;
+
+  die "TRUSTED_CONFIG_LIST $parm_trusted_config_list must not be world writable!\n"
+    if 02 & (stat _)[2];
+
+  die sprintf "TRUSTED_CONFIG_LIST: $parm_trusted_config_list %d is group writable, but not owned by group '%s' or '%s'.\n",
+  (stat _)[1],
+    scalar(getgrgid 0), scalar(getgrgid $>)
+    if (020 & (stat _)[2]) and not ((stat _)[5] == $> or (stat _)[5] == 0);
+
+  die sprintf "TRUSTED_CONFIG_LIST: $parm_trusted_config_list is not owned by user '%s' or '%s'.\n",
+  scalar(getpwuid 0), scalar(getpwuid $>)
+     if (not (-o _ or (stat _)[4] == 0));
+
+  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 { /^$test_config$/ } <TCL>;
+  }
+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 "** Cannot run $parm_exim: $!\n";
 
 open(EXIMINFO, "$parm_exim -bV -C $parm_cwd/test-config -DDIR=$parm_cwd |") ||
   die "** Cannot run $parm_exim: $!\n";
 
@@ -2728,7 +2821,7 @@ $pwcomm = $pwcomm;
 
 $parm_caller_group = getgrgid($parm_caller_gid);
 
 
 $parm_caller_group = getgrgid($parm_caller_gid);
 
-print "Program caller is $parm_caller, whose group is $parm_caller_group\n";
+print "Program caller is $parm_caller ($parm_caller_uid), whose group is $parm_caller_group ($parm_caller_gid)\n";
 print "Home directory is $parm_caller_home\n";
 
 unless (defined $parm_eximgroup)
 print "Home directory is $parm_caller_home\n";
 
 unless (defined $parm_eximgroup)
@@ -3365,6 +3458,7 @@ foreach $test (@test_list)
   $stdout_skip = 0;
   $rmfiltertest = 0;
   $is_ipv6test = 0;
   $stdout_skip = 0;
   $rmfiltertest = 0;
   $is_ipv6test = 0;
+  $TEST_STATE->{munge} = "";
 
   # Remove the associative arrays used to hold checked mail files and msglogs
 
 
   # Remove the associative arrays used to hold checked mail files and msglogs