From 3f9bcc4a0dc2e37b4af0fb533e95b1687ae457f6 Mon Sep 17 00:00:00 2001
From: Fabian Keil <fk@fabiankeil.de>
Date: Sun, 29 Aug 2010 14:12:30 +0200
Subject: [PATCH 1/4] runtests.pl: Add a -P option to specify an external proxy

... that should be used when executing the tests.

This doesn't work for all test types yet.

The assumption is that the proxy is an HTTP proxy and the
mode enables a couple of "tricks" to reduce false positives:

- Set a User-Agent that allows the proxy to detect that the
  request is part of a curl test (only works for tool=curl).
- Filter out "Proxy-Connection:" headers when checking for
  test success.
- Deal with tests that don't expect CRLF header endings as
  long as the test uses it consistently.
- Reduce spaces in headers with a too-simplistic heuristic
  that happens to work for the existing tests.
- Strip connection-established headers if they are unexpected
  by the test.
---
 tests/runtests.pl | 110 ++++++++++++++++++++++++++++++++++++++++++++++++++++++
 1 file changed, 110 insertions(+)

diff --git a/tests/runtests.pl b/tests/runtests.pl
index 99be57d..7d90aa1 100755
--- a/tests/runtests.pl
+++ b/tests/runtests.pl
@@ -114,6 +114,9 @@ my $HOST6IP="[::1]";      # address on which the test server listens
 my $CLIENTIP="127.0.0.1"; # address which curl uses for incoming connections
 my $CLIENT6IP="[::1]";    # address which curl uses for incoming connections
 
+my $use_external_proxy = 0;
+my $proxy_address;
+
 my $base = 8990; # base port number
 
 my $HTTPPORT;            # HTTP server port
@@ -726,6 +729,9 @@ sub verifyhttp {
     $flags .= "--globoff ";
     $flags .= "-1 "         if($has_axtls);
     $flags .= "--insecure " if($proto eq 'https');
+    if($use_external_proxy) {
+        $flags .= " --proxy $proxy_address -H 'User-Agent: curl regression tests' ";
+    }
     $flags .= "\"$proto://$ip:$port/${bonus}verifiedserver\"";
 
     my $cmd = "$VCURL $flags 2>$verifylog";
@@ -800,6 +806,9 @@ sub verifyftp {
     $flags .= "--verbose ";
     $flags .= "--globoff ";
     $flags .= $extra;
+    if($use_external_proxy) {
+        $flags .= " --proxy $proxy_address -H 'User-Agent: curl regression tests' ";
+    }
     $flags .= "\"$proto://$ip:$port/verifiedserver\"";
 
     my $cmd = "$VCURL $flags 2>$verifylog";
@@ -862,6 +871,9 @@ sub verifyrtsp {
     $flags .= "--silent ";
     $flags .= "--verbose ";
     $flags .= "--globoff ";
+    if($use_external_proxy) {
+        $flags .= " --proxy $proxy_address -H 'User-Agent: curl regression tests' ";
+    }
     # currently verification is done using http
     $flags .= "\"http://$ip:$port/verifiedserver\"";
 
@@ -1003,6 +1015,9 @@ sub verifyhttptls {
     $flags .= "--tlsauthtype SRP ";
     $flags .= "--tlsuser jsmith ";
     $flags .= "--tlspassword abc ";
+    if($use_external_proxy) {
+        $flags .= " --proxy $proxy_address -H 'User-Agent: curl regression tests' ";
+    }
     $flags .= "\"https://$ip:$port/verifiedserver\"";
 
     my $cmd = "$VCURL $flags 2>$verifylog";
@@ -2230,6 +2245,12 @@ sub filteroff {
     return 0;
 }
 
+sub print_skipped_header ($) {
+    my $skipped_header = shift;
+    $skipped_header =~ s@\r?\n$@@;
+    print "Skipping '$skipped_header'\n";
+}
+
 #######################################################################
 # compare test results with the expected output, we might filter off
 # some pattern that is allowed to differ, output test results
@@ -2238,6 +2259,82 @@ sub compare {
     # filter off patterns _before_ this comparison!
     my ($testnum, $testname, $subject, $firstref, $secondref)=@_;
 
+    if ($use_external_proxy) {
+        my @tmp;
+        my $crlf_expected = 0;
+        my $connection_header_expected = 0;
+        my $parsing_headers = 0;
+        my $connection_established_expected = 0;
+
+        foreach (@$secondref) {
+            if (/^HTTP/) {
+                $parsing_headers = 1;
+                # This check will likely need modifications for other proxies
+                if (/Connection established/) {
+                    $connection_established_expected = 1;
+                }
+            }
+            if (/^\r?\n$/) {
+                $parsing_headers = 0;
+            }
+            if (/\r\n$/) {
+                $crlf_expected = 1; # XXX: assume the expectancy is consistant.
+            }
+            if (/^Connection:/) {
+                $connection_header_expected = 1;
+            }
+            if (/^Connection:/) {
+                $connection_header_expected = 1;
+            }
+            if ($parsing_headers) {
+                # This is probably a header, normalize spaces
+                # similar to the way Privoxy does. This is required
+                # for tests 29, 40, 42 and 54.
+                # XXX: this is a hack
+                next if /"/;
+                s@  +@ @g;
+            }
+        }
+
+        if($verbose) {
+            print "Expecting " . ($crlf_expected ? "" : "no ") . "crlf\n";
+            print "Expecting " . ($connection_header_expected ? "a" : "no") . " Connection: header\n";
+            print "Expecting " . ($connection_established_expected ? "" : "no ") . "Connection established\n";
+        }
+
+        $parsing_headers = 0;
+        my $remove_headers = 0;
+        foreach (@$firstref) {
+            if (/^HTTP/) {
+                $parsing_headers = 1;
+                # This check will likely need modifications for other proxies
+                if (!$connection_established_expected && /Connection established/) {
+                     $remove_headers = 1;
+                }
+            }
+            if ($remove_headers) {
+                print_skipped_header($_) if($verbose);
+                $remove_headers = 0 if (/^\r?\n$/);
+                next;
+            }
+            if (/^\r?\n$/) {
+                $parsing_headers = 0;
+            }
+
+            s@\r\n$@\n@ unless ($crlf_expected);
+            if (m/^Proxy-Connection: keep-alive/ or m/^User-Agent: curl regression tests/) {
+                print_skipped_header($_) if($verbose);
+                next;
+            }
+            if (m/^Connection:/ and not $connection_header_expected) {
+                print_skipped_header($_) if($verbose);
+                next;
+            }
+            push @tmp, $_;
+        }
+        $firstref = \@tmp;
+    }
+
     my $result = compareparts($firstref, $secondref);
 
     if($result) {
@@ -3090,6 +3187,10 @@ sub singletest {
             }
         }
     }
+    if($use_external_proxy) {
+        $ENV{http_proxy} = $proxy_address;
+        $ENV{HTTPS_PROXY} = $proxy_address;
+    }
 
     if(!$why) {
         # TODO:
@@ -3317,6 +3418,9 @@ sub singletest {
             $fail_due_event_based--;
         }
         $cmdargs .= $cmd;
+        if ($use_external_proxy) {
+            $cmdargs .= " --proxy $proxy_address -H 'User-Agent: curl regression tests'";
+        }
     }
     else {
         $cmdargs = " $cmd"; # $cmd is the command line for the test file
@@ -4659,6 +4763,11 @@ while(@ARGV) {
     elsif($ARGV[0] eq "-p") {
         $postmortem=1;
     }
+    elsif($ARGV[0] eq "-P") {
+        shift @ARGV;
+        $use_external_proxy=1;
+        $proxy_address=$ARGV[0];
+    }
     elsif($ARGV[0] eq "-l") {
         # lists the test case names only
         $listonly=1;
@@ -4710,6 +4819,7 @@ Usage: runtests.pl [options] [test selection(s)]
   -l       list all test case names/descriptions
   -n       no valgrind
   -p       print log file contents when a test fails
+  -P proxy use the specified proxy
   -r       run time statistics
   -rf      full run time statistics
   -s       short output
-- 
1.9.0


