You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@trafficserver.apache.org by bc...@apache.org on 2019/01/11 19:10:50 UTC

[trafficserver] branch master updated: Compare servers script for comparing responses from new and old versions of ATS

This is an automated email from the ASF dual-hosted git repository.

bcall pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/trafficserver.git


The following commit(s) were added to refs/heads/master by this push:
     new 72e9db6  Compare servers script for comparing responses from new and old versions of ATS
72e9db6 is described below

commit 72e9db6a523e54c937f21d91bc74a608237de7e0
Author: Bryan Call <bc...@apache.org>
AuthorDate: Thu Nov 29 14:58:51 2018 -0800

    Compare servers script for comparing responses from new and old versions of ATS
---
 tools/compare_servers.pl | 245 +++++++++++++++++++++++++++++++++++++++++++++++
 1 file changed, 245 insertions(+)

diff --git a/tools/compare_servers.pl b/tools/compare_servers.pl
new file mode 100755
index 0000000..7f1bcb8
--- /dev/null
+++ b/tools/compare_servers.pl
@@ -0,0 +1,245 @@
+#!/usr/bin/perl
+#
+# Licensed to the Apache Software Foundation (ASF) under one
+# or more contributor license agreements.  See the NOTICE file
+# distributed with this work for additional information
+# regarding copyright ownership.  The ASF licenses this file
+# to you under the Apache License, Version 2.0 (the
+# "License"); you may not use this file except in compliance
+# with the License.  You may obtain a copy of the License at
+#
+#      http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+use strict;
+use warnings;
+use Getopt::Long;
+use Data::Dumper;
+use Net::hostent;
+use Socket;
+use LWP::UserAgent;
+use Digest::SHA1;
+
+my $verbose = 0;
+
+#----------------------------------------------------------------------------
+sub usage() {
+  print STDERR "USAGE: compare_hosts.pl --verbose level --host1 testing_host --host2 valid_host --file url_file\n\n";
+  print STDERR "\t--host1         The host running the newest version\n";
+  print STDERR "\t--host2         The host running the older version\n";
+  print STDERR "\t--file          A file that contains a list of URLs\n";
+  print STDERR "\t--verbose       verbose level 1-3, 1 is the least verbose\n\n";
+  print STDERR "Example:\n";
+  print STDERR "\tcompare_hosts.pl --host1 new_ats --host2 old_ats --file top_1000_urls\n";
+  exit 1;
+}
+
+#----------------------------------------------------------------------------
+sub compareHeaderNames($$) {
+  my($response1, $response2) = @_;
+
+  my @names1 = $response1->header_field_names;
+  my @names2 = $response2->header_field_names;
+
+  my %hash2;
+  $hash2{$_} = 1 for (@names2);
+  my %hash1;
+  $hash1{$_} = 1 for (@names1);
+
+  my $return_val = 0; # header names match
+
+  foreach my $name (@names1) {
+    if (!defined $hash2{$name}) {
+      print "\t\t- $name header not found on host2\n" if $verbose >= 2;
+      $return_val = 1;
+    }
+  }
+
+  foreach my $name (@names2) {
+    if (!defined $hash1{$name}) {
+      print "\t\t- $name header not found on host1\n" if $verbose >= 2;
+      $return_val = 1;
+    }
+  }
+
+  return $return_val;
+}
+
+#----------------------------------------------------------------------------
+sub compareHeaderValues($$) {
+  my($response1, $response2) = @_;
+
+  my @test_headers = qw(ETag Cache-Control Connection Accept-Ranges Server Content-Type Access-Control-Allow-Methods Access-Control-Allow-Origin Strict-Transport-Security);
+  my $return_val = 0; # header valuse match
+
+  if ($verbose >= 3) {
+    foreach my $field ($response1->header_field_names) {
+      print "\t\t\t~ " . $field . ": " . $response1->header($field) . "\n";
+    }
+
+    print "\t\tHost2: \n";
+
+    foreach my $field ($response2->header_field_names) {
+      print "\t\t\t~ " . $field . ": " . $response2->header($field) . "\n";
+    }
+  }
+
+  # Test specific headers that are defined above
+  foreach my $field (@test_headers) {
+    my $value1 = $response1->header($field);
+    my $value2 = $response2->header($field);
+
+    if (defined $value1 && defined $value2) {
+      if ($value1 ne $value2) {
+        print "\t\t- $field: $value1 ne $value2\n" if $verbose;
+        print "\t\t\t - Via host1: " . $response1->header('Via') . " host2: " . $response2->header('Via') . "\n" if $verbose;
+        print "\t\t\t - Last-Modified host1: " . $response1->header('Last-Modified') . " host2: " . $response2->header('Last-Modified') . "\n" if $verbose;
+        if (defined $response2->header('Content-Encoding')) {
+         print "\t\t\t - Content-Encoding host1: " . $response1->header('Content-Encoding') . " host2: " . $response2->header('Content-Encoding') . "\n";
+        } else {
+          print "\t\t\t - Content-Encoding host1: " . $response1->header('Content-Encoding') . " host2: ''\n";
+        }
+        $return_val = 1;
+      } else {
+        print "\t\t- $field: $value1 eq $value2\n" if $verbose >= 2;
+      }
+    }
+  }
+  return $return_val;
+}
+
+#----------------------------------------------------------------------------
+{
+  my %stats;
+
+  $ENV{PERL_LWP_SSL_VERIFY_HOSTNAME} = '0';
+  my($host1, $host2, $file);
+  GetOptions ("host1=s" => \$host1,
+              "host2=s"   => \$host2,
+              "file=s"  => \$file,
+              "verbose=f" => \$verbose) || die $!;
+
+  usage() if (! defined $host1 || ! defined $host2 || ! defined $file);
+
+  my $count = 0;
+  my $status_error = 0;
+  my $sha_error = 0;
+  my $header_names_mismatch = 0;
+  my $header_values_mismatch = 0;
+
+  my $host1_addr = inet_ntoa(inet_aton($host1));
+  my $host2_addr = inet_ntoa(inet_aton($host2));
+
+  print "Testing with host1: $host1 ($host1_addr) - host2: $host2 ($host2_addr)\n";
+  print '-' x 78, "\n";
+
+  open(FILE, $file) || die $!;
+
+  # Create a user agent object
+  my $ua1 = LWP::UserAgent->new(keep_alive => 100);
+  $ua1->agent("MyApp/0.1 ");
+
+  # Create a user agent object
+  my $ua2 = LWP::UserAgent->new(keep_alive => 100);
+  $ua2->agent("MyApp/0.1 ");
+
+  while (my $url = <FILE>) {
+    next if ($url =~ m|hc.l.yimg.com|);
+    chomp $url;
+    my $exit = 0;
+
+    if ($url =~ m|(https?)://([^/]+)(.+)|) {
+
+      my $scheme = $1;
+      my $host = $2;
+      my $path = $3;
+
+      $count++;
+      print "Test $count - URL: $url\n";
+
+      my $port = 80;
+      $port = 443 if $scheme eq 'https';
+
+      my $request1 = HTTP::Request->new(GET => "${scheme}://${host1_addr}${path}");
+      $request1->header('Host' => $host);
+      my $response1 = $ua1->request($request1);
+
+      my $request2 = HTTP::Request->new(GET => "${scheme}://${host2_addr}${path}");
+      $request2->header('Host' => $host);
+      $request2->header('Accept-Encoding' => 'deflate');
+      my $response2 = $ua2->request($request2);
+
+      print "\tStatus code for host1: " . $response1->code . " - host2: " . $response2->code . "\n" if $verbose;
+
+      my $sha1 = Digest::SHA1->new;
+      $sha1->add($response1->content);
+      my $digest1 = $sha1->hexdigest;
+      open(FILE1, "> /tmp/tmp1");
+      open(FILE2, "> /tmp/tmp2");
+      print FILE1 $response1->content;
+      print FILE2 $response2->content;
+      close FILE1;
+      close FILE2;
+      #print $response1->content, "\n"; # for internal debugging
+      #print $response2->content, "\n"; # for internal debugging
+
+      my $sha2 = Digest::SHA1->new;
+      $sha2->add($response2->content);
+      my $digest2 = $sha2->hexdigest;
+
+      print "\tSHA hash for host1: $digest1 - host2: $digest2\n" if $verbose;
+
+      # Build up stats
+      if ($response1->status_line eq $response2->status_line) {
+
+        # Do the hashes
+        if ($digest1 eq $digest2) {
+          $stats{stat_line_match}->{$response1->code}->{sha_match}++;
+          print "\tResponse code: " . $response1->code . " - Status lines and SHA1 of response bodies match\n";
+        } else {
+          $stats{stat_line_match}->{$response1->code}->{sha_nomatch}++;
+          print "\tResponse code: " . $response1->code . " - Status lines match SHA1 doesn't match\n";
+          $sha_error++;
+          #$exit = 1 if $response1->code == 200; # for internal debugging
+        }
+
+        # Compare the header field names
+        if (compareHeaderNames($response1, $response2) == 0) {
+          $stats{stat_line_match}->{$response1->code}->{field_names_match}++;
+        } else {
+          $stats{stat_line_match}->{$response1->code}->{field_names_nomatch}++;
+          $header_names_mismatch++;
+        }
+
+        # Compare the values of the header fields
+        if (compareHeaderValues($response1, $response2) == 0) {
+          $stats{stat_line_match}->{$response1->code}->{field_values_match}++;
+        } else {
+          $stats{stat_line_match}->{$response1->code}->{field_values_nomatch}++;
+          $header_values_mismatch++;
+        }
+      } else {
+         $status_error++;
+         $stats{stat_line_nomatch}++;
+         print "\tERROR: status lines don't match\n";
+      }
+
+      last if $exit;
+    }
+  }
+
+  print '-' x 78, "\n";
+  print "SUMMARY:\n";
+  print "URLs tested: $count\n";
+  print "Status line mismatches: $status_error\n";
+  print "SHA1 mismatches: $sha_error\n";
+  print "Responses with header names mismatches: $header_names_mismatch\n";
+  print "Responses with header values mismatches: $header_values_mismatch\n";
+  print Dumper \%stats if $verbose;
+}
+