Testsuite: DKIM/transport_filter testcase
[users/jgh/exim.git] / test / runtest
index 1b6eaabb002f66dfefd4e17d8131fcdcb29d255c..87a475ccd38f0978f1a572e3ac5a2ad387967222 100755 (executable)
@@ -112,7 +112,7 @@ $ENV{LC_ALL} = 'C';
 $ENV{USER} = getpwuid($>) if not exists $ENV{USER};
 
 my ($parm_configure_owner, $parm_configure_group);
-my ($parm_ipv4, $parm_ipv6);
+my ($parm_ipv4, $parm_ipv6, $parm_ipv6_stripped);
 my $parm_hostname;
 
 ###############################################################################
@@ -758,6 +758,10 @@ RESET_AFTER_EXTRA_LINE_READ:
   s/waiting for children of \d+/waiting for children of pppp/;
   s/waiting for (\S+) \(\d+\)/waiting for $1 (pppp)/;
 
+  # Most builds are without HAVE_LOCAL_SCAN
+  next if /^calling local_scan\(\); timeout=300$/;
+  next if /^local_scan\(\) returned 0 NULL$/;
+
   # ======== Port numbers ========
   # Incoming port numbers may vary, but not in daemon startup line.
 
@@ -772,7 +776,7 @@ RESET_AFTER_EXTRA_LINE_READ:
     }
 
   # Port in host address in spool file output from -Mvh
-  s/^-host_address (.*)\.\d+/-host_address $1.9999/;
+  s/^(--?host_address) (.*)\.\d+/$1 $2.9999/;
 
   if ($dynamic_socket and $dynamic_socket->opened and my $port = $dynamic_socket->sockport) {
     s/^Connecting to 127\.0\.0\.1 port \K$port/<dynamic port>/;
@@ -794,6 +798,7 @@ RESET_AFTER_EXTRA_LINE_READ:
   s/host\s\Q$parm_ipv6\E\s\[\Q$parm_ipv6\E\]/host ip6:ip6:ip6:ip6:ip6:ip6:ip6:ip6 [ip6:ip6:ip6:ip6:ip6:ip6:ip6:ip6]/;
   s/\b\Q$parm_ipv4\E\b/ip4.ip4.ip4.ip4/g;
   s/(^|\W)\K\Q$parm_ipv6\E/ip6:ip6:ip6:ip6:ip6:ip6:ip6:ip6/g;
+  s/(^|\W)\K\Q$parm_ipv6_stripped\E/ip6:ip6:ip6:ip6:ip6:ip6:ip6:ip6/g;
   s/\b\Q$parm_ipv4r\E\b/ip4-reverse/g;
   s/(^|\W)\K\Q$parm_ipv6r\E/ip6-reverse/g;
   s/^(\s+host\s\S+\s+\[\S+\]) +$/$1 /;
@@ -1085,7 +1090,7 @@ RESET_AFTER_EXTRA_LINE_READ:
     next if /name=localhost address=::1/;
 
     # drop pdkim debugging header
-    next if /^PDKIM( <<<<<<<<<<<<<<<<<<<<<<<<<<<<<+|: no signatures)$/;
+    next if /^DKIM( <<<<<<<<<<<<<<<<<<<<<<<<<<<<<+|: no signatures)$/;
 
     # Various other IPv6 lines must be omitted too
 
@@ -1093,6 +1098,8 @@ RESET_AFTER_EXTRA_LINE_READ:
     next if /get\[host\|ipnode\]byname\[2\]\(af=inet6\)/;
     next if /DNS lookup of \S+ \(AAAA\) using fakens/;
     next if / in dns_ipv4_lookup?/;
+    next if / writing neg-cache entry for .*AAAA/;
+    next if /^faking res_search\(AAAA\) response length as 65535/;
 
     if (/DNS lookup of \S+ \(AAAA\) gave NO_DATA/)
       {
@@ -1100,6 +1107,17 @@ 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$/)
+      {
+      $_= <IN>; $_= <IN>; $_= <IN>; $_= <IN>;
+      $_= <IN>; $_= <IN>; $_= <IN>; $_= <IN>;
+      $_= <IN>; $_= <IN>; $_= <IN>; next;
+      }
+
+
     # Skip tls_advertise_hosts and hosts_require_tls checks when the options
     # are unset, because tls ain't always there.
 
@@ -1154,11 +1172,20 @@ RESET_AFTER_EXTRA_LINE_READ:
     # remote port numbers vary
     s/(Connection request from 127.0.0.1 port) \d{1,5}/$1 sssss/;
 
+    # Platform-dependent error strings
+    s/Operation timed out/Connection timed out/;
+
+    # Platform-dependent resolver option bits
+    s/^ (?:writing|update) neg-cache entry for [^,]+-\K[0-9a-f]+, ttl/xxxx, ttl/;
+
+    # timing variance, run-to-run
+    s/^time on queue = \K1s/0s/;
+
     # Skip hosts_require_dane checks when the options
     # are unset, because dane ain't always there.
     next if /in\shosts_require_dane\?\sno\s\(option\sunset\)/x;
 
-    # DISABLE_OCSP 
+    # DISABLE_OCSP
     next if /in hosts_requ(est|ire)_ocsp\? (no|yes)/;
 
     # SUPPORT_PROXY
@@ -1198,20 +1225,24 @@ RESET_AFTER_EXTRA_LINE_READ:
       }
 
     # Not all platforms build with DKIM enabled
-    next if /^PDKIM >> Body data for hash, canonicalized/;
+    next if /^DKIM >> Body data for hash, canonicalized/;
+
+    # Not all platforms build with SPF enabled
+    next if /^(spf_conn_init|SPF_dns_exim_new|spf_compile\.c)/;
 
     # Not all platforms have sendfile support
     next if /^cannot use sendfile for body: no support$/;
 
     #  Parts of DKIM-specific debug output depend on the time/date
     next if /^date:\w+,\{SP\}/;
-    next if /^PDKIM \[[^[]+\] (Header hash|b) computed:/;
+    next if /^DKIM \[[^[]+\] (Header hash|b) computed:/;
 
     # Not all platforms support TCP Fast Open, and the compile omits the check
     if (s/\S+ in hosts_try_fastopen\? (no \(option unset\)|yes \(matched "\*"\))\n$//)
       {
       $_ .= <IN>;
       s/ \.\.\. >>> / ... /;
+      if (s/ non-TFO mode connection attempt to 224.0.0.0, 0 data\b$//) { $_ .= <IN>; }
       s/Address family not supported by protocol family/Network Error/;
       s/Network is unreachable/Network Error/;
       }
@@ -1220,23 +1251,23 @@ RESET_AFTER_EXTRA_LINE_READ:
 
     if (/^([0-9: ]*                                            # possible timestamp
        Connecting\ to\ [^ ]+\ [^ ]+(\ from\ [^ ]+)?)\ \.\.\.
-       \ .*TFO\ mode\ 
+       \ .*TFO\ mode\x20
        (sendto,\ no\ data:\ EINPROGRESS                        # Linux
-       |connection\ attempt\ to\ [^,]+,\ 0\ data)              # MacOS
+       |connection\ attempt\ to\ [^,]+,\ 0\ data)              # MacOS & no-support
        $/x)
       {
       $_ = $1 . " ... " . <IN>;
-      s/^(.* \.\.\.) [0-9: ]*connected$/$1 connected/;
+      s/^(.* \.\.\.) [0-9: ]*connected$/$1  connected/;
 
-      if (/^Connecting to .* \.\.\. connected$/)
+      if (/^Connecting to .* \.\.\.  connected$/)
        {
        $_ .= <IN>;
-       if (/^(Connecting to .* \.\.\. )connected\n\s+SMTP(\(close\)>>|\(Connection refused\)<<)$/)
+       if (/^(Connecting to .* \.\.\.  )connected\n\s+SMTP(\(close\)>>|\(Connection refused\)<<)$/)
          {
          $_ = $1 . "failed: Connection refused\n" . <IN>;
          s/^(Connecting .*)\n\s+SMTP\(close\)>>$/$1/;
          }
-       elsif (/^(Connecting to .* \.\.\. connected\n)read response data: size=/)
+       elsif (/^(Connecting to .* \.\.\.  connected\n)read response data: size=/)
          { $_ = $1; }
 
        # Date/time in SMTP banner
@@ -1260,6 +1291,9 @@ RESET_AFTER_EXTRA_LINE_READ:
     # TLS resumption is not always supported by the build
     next if /in tls_resumption_hosts\?/;
 
+    # Platform differences in errno strings
+    s/  SMTP\(Operation timed out\)<</  SMTP(Connection timed out)<</;
+
     # When Exim is checking the size of directories for maildir, it uses
     # the check_dir_size() function to scan directories. Of course, the order
     # of the files that are obtained using readdir() varies from system to
@@ -1318,7 +1352,7 @@ RESET_AFTER_EXTRA_LINE_READ:
 
     # openssl version variances
     s/(TLS error on connection [^:]*: error:)[0-9A-F]{8}(:system library):(?:fopen|func\(4095\)):(No such file or directory)$/$1xxxxxxxx$2:fopen:$3/;
-    s/(DANE attempt failed.*error:)[0-9A-F]{8}(:SSL routines:)(ssl3_get_server_certificate|tls_process_server_certificate|CONNECT_CR_CERT)(?=:certificate verify failed$)/$1xxxxxxxx$2ssl3_get_server_certificate/;
+    s/(DANE attempt failed.*error:)[0-9A-F]{8}(:SSL routines:)(?:(?i)ssl3_get_server_certificate|tls_process_server_certificate|CONNECT_CR_CERT)(?=:certificate verify failed$)/$1xxxxxxxx$2ssl3_get_server_certificate/;
     s/(DKIM: validation error: )error:[0-9A-F]{8}:rsa routines:(?:(?i)int_rsa_verify|CRYPTO_internal):(?:bad signature|algorithm mismatch)$/$1Public key signature verification has failed./;
     s/ARC: AMS signing: privkey PEM-block import: error:\K[0-9A-F]{8}:(PEM routines):get_name:(no start line)/0906D06C:$1:PEM_read_bio:$2/;
 
@@ -1734,7 +1768,7 @@ $munges =
     },
 
     'debug_pid' =>
-    { 'stderr' => 's/(^\s{0,4}|(?<=Process )|(?<=child ))\d{1,5}/ppppp/g' },
+    { 'stderr' => 's/(^\s{0,4}|(?<=Process )|(?<=child ))\d+/ppppp/g' },
 
     'optional_dsn_info' =>
     { 'mail' => '/^(X-(Remote-MTA-(smtp-greeting|helo-response)|Exim-Diagnostic|(body|message)-linecount):|Remote-MTA: X-ip;)/'
@@ -2513,9 +2547,24 @@ elsif (/^((?i:[A-Z\d_]+=\S+\s+)+)?(\d+)?\s*(sudo(?:\s+-u\s+(\w+))?\s+)?exim(_\S+
 
   if ($args =~ /\$msg/)
     {
-    my @listcmd  = ("$parm_cwd/eximdir/exim", '-bp',
+    my($queuespec);
+    if ($args =~ /-qG\w+/) { $queuespec = $&; }
+
+    my @listcmd;
+
+    if (defined $queuespec)
+      {
+      @listcmd  = ("$parm_cwd/eximdir/exim", '-bp',
+                  $queuespec,
                    "-DEXIM_PATH=$parm_cwd/eximdir/exim",
                    -C => "$parm_cwd/test-config");
+      }
+    else
+      {
+      @listcmd  = ("$parm_cwd/eximdir/exim", '-bp',
+                   "-DEXIM_PATH=$parm_cwd/eximdir/exim",
+                   -C => "$parm_cwd/test-config");
+      }
     print ">> Getting queue list from:\n>>    @listcmd\n" if $debug;
     # We need the message ids sorted in ascending order.
     # Message id is: <timestamp>-<pid>-<fractional-time>. On some systems (*BSD) the
@@ -3382,21 +3431,28 @@ else
 
 # Find this host's IP addresses - there may be many, of course, but we keep
 # one of each type (IPv4 and IPv6).
+#XXX it would be good to avoid non-UP interfaces
 
 open(IFCONFIG, '-|', (grep { -x "$_/ip" } split /:/, $ENV{PATH}) ? 'ip address' : 'ifconfig -a')
   or die "** Cannot run 'ip address' or 'ifconfig -a'\n";
 while (not ($parm_ipv4 and $parm_ipv6) and defined($_ = <IFCONFIG>))
   {
+  if (/^(?:[0-9]+: )?([a-z0-9]+): /) { $ifname = $1; }
+
   if (not $parm_ipv4 and /^\s*inet(?:\saddr)?:?\s?(\d+\.\d+\.\d+\.\d+)(?:\/\d+)?\s/i)
     {
-    next if $1 =~ /^(?:127|10)\./;
+    # It would be nice to be able to vary the /16 used for manyhome; we could take
+    # an option to runtest used here - but we'd also have to pass it on to fakens.
+    # Possibly an environment variable?
+    next if $1 eq '0.0.0.0' or $1 =~ /^(?:127|10\.250)\./;
     $parm_ipv4 = $1;
     }
 
   if (not $parm_ipv6 and /^\s*inet6(?:\saddr)?:?\s?([abcdef\d:]+)(?:%[^ \/]+)?(?:\/\d+)?/i)
     {
-    next if $1 eq '::1' or $1 =~ /^fe80/i;
+    next if $1 eq '::' or $1 eq '::1' or $1 =~ /^ff00/i or $1 =~ /^fe80::1/i;
     $parm_ipv6 = $1;
+    if ($1 =~ /^fe80/i) { $parm_ipv6 .= '%' . $ifname; }
     }
   }
 close(IFCONFIG);
@@ -3454,6 +3510,8 @@ else
 print "IPv4 address is $parm_ipv4\n";
 print "IPv6 address is $parm_ipv6\n";
 $parm_ipv6 =~ /^[^%\/]*/;
+# drop any %scope from the ipv6, for some uses
+($parm_ipv6_stripped = $parm_ipv6) =~ s/%.*//g;
 
 # For munging test output, we need the reversed IP addresses.
 
@@ -3463,7 +3521,7 @@ $parm_ipv4r = ($parm_ipv4 !~ /^\d/)? '' :
 $parm_ipv6r = $parm_ipv6;             # Appropriate if not in use
 if ($parm_ipv6 =~ /^[\da-f]/)
   {
-  my(@comps) = split /:/, $parm_ipv6;
+  my(@comps) = split /:/, $parm_ipv6_stripped;
   my(@nibbles);
   foreach $comp (@comps)
     {
@@ -3884,7 +3942,7 @@ if ($have_ipv4 || $have_ipv6)
     "; for queries that it cannot answer\n\n" .
     "PASS ON NOT FOUND\n\n";
   print OUT "$shortname  A     $parm_ipv4\n" if $have_ipv4;
-  print OUT "$shortname  AAAA  $parm_ipv6\n" if $have_ipv6;
+  print OUT "$shortname  AAAA  $parm_ipv6_stripped\n" if $have_ipv6;
   print OUT "\n; End\n";
   close(OUT);
   }
@@ -3892,28 +3950,39 @@ if ($have_ipv4 || $have_ipv6)
 if ($have_ipv4 && $parm_ipv4 ne "127.0.0.1")
   {
   my(@components) = $parm_ipv4 =~ /^(\d+)\.(\d+)\.(\d+)\.(\d+)/;
-  open(OUT, ">$parm_cwd/dnszones/db.ip4.$components[0]") ||
-    tests_exit(-1,
-      "Failed  to open $parm_cwd/dnszones/db.ip4.$components[0]: $!");
-  print OUT "; This is a dynamically constructed fake zone file.\n" .
-    "; The zone is $components[0].in-addr.arpa.\n\n" .
-    "$components[3].$components[2].$components[1]  PTR  $parm_hostname.\n\n" .
-    "; End\n";
-  close(OUT);
+
+  if ($components[0]=='10')
+    {
+    open(OUT, ">>$parm_cwd/dnszones/db.ip4.$components[0]") ||
+      tests_exit(-1, "Failed  to open $parm_cwd/dnszones/db.ip4.$components[0]: $!");
+    print OUT "$components[3].$components[2].$components[1]  PTR  $parm_hostname.\n\n";
+    close(OUT);
+    } 
+  else
+    {
+    open(OUT, ">$parm_cwd/dnszones/db.ip4.$components[0]") ||
+      tests_exit(-1,
+       "Failed  to open $parm_cwd/dnszones/db.ip4.$components[0]: $!");
+    print OUT "; This is a dynamically constructed fake zone file.\n" .
+      "; The zone is $components[0].in-addr.arpa.\n\n" .
+      "$components[3].$components[2].$components[1]  PTR  $parm_hostname.\n\n" .
+      "; End\n";
+    close(OUT);
+    }
   }
 
-if ($have_ipv6 && $parm_ipv6 ne "::1")
+if ($have_ipv6 && $parm_ipv6_stripped ne "::1")
   {
-  my($exp_v6) = $parm_ipv6;
+  my($exp_v6) = $parm_ipv6_stripped;
   $exp_v6 =~ s/[^:]//g;
-  if ( $parm_ipv6 =~ /^([^:].+)::$/ ) {
+  if ( $parm_ipv6_stripped =~ /^([^:].+)::$/ ) {
     $exp_v6 = $1 . ':0' x (9-length($exp_v6));
-  } elsif ( $parm_ipv6 =~ /^(.+)::(.+)$/ ) {
+  } elsif ( $parm_ipv6_stripped =~ /^(.+)::(.+)$/ ) {
     $exp_v6 = $1 . ':0' x (8-length($exp_v6)) . ':' . $2;
-  } elsif ( $parm_ipv6 =~ /^::(.+[^:])$/ ) {
+  } elsif ( $parm_ipv6_stripped =~ /^::(.+[^:])$/ ) {
     $exp_v6 = '0:' x (9-length($exp_v6)) . $1;
   } else {
-    $exp_v6 = $parm_ipv6;
+    $exp_v6 = $parm_ipv6_stripped;
   }
   my(@components) = split /:/, $exp_v6;
   my(@nibbles) = reverse (split /\s*/, shift @components);
@@ -4218,10 +4287,22 @@ foreach $test (@test_list)
           print "==================>\n";
           system("tail -20 test-stdout");
           print "===================\n";
+
           print "stderr tail:\n";
           print "==================>\n";
-          system("tail -20 test-stderr");
+          system("tail -30 test-stderr");
+          print "===================\n";
+
+          print "stdout-server tail:\n";
+          print "==================>\n";
+          system("tail -20 test-stdout-server");
           print "===================\n";
+
+          print "stderr-server tail:\n";
+          print "==================>\n";
+          system("tail -30 test-stderr-server");
+          print "===================\n";
+
           print "... continue forced\n";
           }