Testsuite: Fix the [U]pdate for new testcases
[users/heiko/exim.git] / test / runtest
index 4247f8c53b9a8dba352b86fec63c7ceececaf3ec..f215bf4debff51ba8dd36c5352269611720095d1 100755 (executable)
 ###############################################################################
 
 #use strict;
-require Cwd;
 use Errno;
 use FileHandle;
 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
@@ -43,6 +45,7 @@ $more = "less -XF";
 $optargs = "";
 $save_output = 0;
 $server_opts = "";
+$flavour = 'FOO';
 
 $have_ipv4 = 1;
 $have_ipv6 = 1;
@@ -320,6 +323,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/;
@@ -1067,7 +1072,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];
@@ -1130,7 +1135,13 @@ my($rf,$rsf,$mf,$sf,$sortfile,$extra) = @_;
 # If there is no saved file, the raw files must either not exist, or be
 # empty. The test ! -s is TRUE if the file does not exist or is empty.
 
-if (! -e $sf)
+# we check if there is a flavour specific file, but we remember
+# the original file name as "generic"
+$sf_generic = $sf;
+$sf_flavour = "$sf_generic.$flavour";
+$sf_current = -e $sf_flavour ? $sf_flavour : $sf_generic;
+
+if (! -e $sf_current)
   {
   return 0 if (! -s $rf && (! defined $rsf || ! -s $rsf));
 
@@ -1170,6 +1181,8 @@ if (! -e $sf)
     }
   }
 
+#### $_
+
 # 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.
@@ -1197,7 +1210,7 @@ close(MUNGED);
 # a result of parallel deliveries. We load the munged file and sort sequences
 # of delivery lines.
 
-if (-e $sf)
+if (-e $sf_current)
   {
   # Deal with truncated text items
 
@@ -1208,7 +1221,7 @@ if (-e $sf)
     open(MUNGED, "$mf") || tests_exit(-1, "Failed to open $mf: $!");
     @munged = <MUNGED>;
     close(MUNGED);
-    open(SAVED, "$sf") || tests_exit(-1, "Failed to open $sf: $!");
+    open(SAVED, $sf_current) || tests_exit(-1, "Failed to open $sf_current: $!");
     @saved = <SAVED>;
     close(SAVED);
 
@@ -1270,31 +1283,46 @@ if (-e $sf)
 
   # Do the comparison
 
-  return 0 if (system("$cf '$mf' '$sf' >test-cf") == 0);
+  return 0 if (system("$cf '$mf' '$sf_current' >test-cf") == 0);
 
   # Handle comparison failure
 
-  print "** Comparison of $mf with $sf failed";
+  print "** Comparison of $mf with $sf_current failed";
   system("$more test-cf");
 
   print "\n";
   for (;;)
     {
-    interact("Continue, Retry, Update & retry, Quit? [Q] ", $force_update, $force_continue);
+    interact("Continue, Retry, Update current"
+       . ($sf_current ne $sf_flavour  ? "/Save for flavour '$flavour'" : "")
+       . " & retry, Quit? [Q] ", $force_update, $force_continue);
     tests_exit(1) if /^q?$/i;
-    log_failure($log_failed_filename, $testno, $sf) if (/^c$/i && $force_continue);
+    log_failure($log_failed_filename, $testno, $sf_current) if (/^c$/i && $force_continue);
     return 0 if /^c$/i;
     return 1 if /^r$/i;
-    last if (/^u$/i);
+    last if (/^[us]$/i);
     }
   }
 
 # Update or delete the saved file, and give the appropriate return code.
 
 if (-s $mf)
-  { tests_exit(-1, "Failed to cp $mf $sf") if system("cp '$mf' '$sf'") != 0; }
+  {
+       my $sf = /^u/i ? $sf_current : $sf_flavour;
+               tests_exit(-1, "Failed to cp $mf $sf") if system("cp '$mf' '$sf'") != 0;
+  }
 else
-  { tests_exit(-1, "Failed to unlink $sf") if !unlink($sf); }
+  {
+       # if we deal with a flavour file, we can't delete it, because next time the generic
+       # file would be used again
+       if ($sf_current eq $sf_flavour) {
+               open(FOO, ">$sf_current");
+               close(FOO);
+       }
+       else {
+               tests_exit(-1, "Failed to unlink $sf_current") if !unlink($sf_current);
+       }
+  }
 
 return 1;
 }
@@ -1903,7 +1931,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);
@@ -1917,10 +1946,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;
   }
 
@@ -2096,6 +2124,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");
@@ -2106,12 +2135,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/)
@@ -2253,9 +2293,10 @@ else
 ##################################################
 
 # 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 "";
 
 
@@ -2282,6 +2323,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 =~ /^-FLAVOU?R$/) { $flavour = shift; next; }
     }
   $optargs .= " $arg";
   }
@@ -3109,7 +3151,7 @@ else
 # because the current binary does not support the right facilities, and also
 # those that are outside the numerical range selected.
 
-print "\nTest range is $test_start to $test_end\n";
+print "\nTest range is $test_start to $test_end (flavour $flavour)\n";
 print "Omitting \${dlfunc expansion tests (loadable module not present)\n"
   if $dlfunc_deleted;
 print "Omitting dbm tests (unable to copy exim_dbmbuild)\n"
@@ -3215,7 +3257,7 @@ for ($i = 0; $i < @test_dirs; $i++)
 
   foreach $test (@testlist)
     {
-    next if $test !~ /^\d{4}$/;
+    next if $test !~ /^\d{4}(?:\.\d+)?$/;
     next if $test < $test_start || $test > $test_end;
     push @test_list, "$testdir/$test";
     }
@@ -3401,7 +3443,7 @@ foreach $test (@test_list)
   local($lineno) = 0;
   local($commandno) = 0;
   local($subtestno) = 0;
-  local($testno) = substr($test, -4);
+  (local $testno = $test) =~ s|.*/||;
   local($sortlog) = 0;
 
   my($gnutls) = 0;
@@ -3566,6 +3608,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) {