aboutsummaryrefslogtreecommitdiff
path: root/final/HTMLColDiff.pl
blob: 3e740fbcc357141d2a5b53d55f409fdfd5f8c258 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
#!/usr/bin/perl -w

use strict;

# htmlcoldiff - Diff two files (specified on the command line) laid out in
# columns.  Output a copy of the second file with differences from the first
# hi-lighted in bold (with HTML tags).  This assumes that the first column of
# the file is an identifier that keys two rows of the files together.
#

# Don't show changes smaller than 1% by default
my $showThreshold = 1;
# Highlight changes larger than 5% by default
my $highlightThreshold = 5;
# Don't highlight changes that have a smaller absolute difference than this
my $highlightAbsDiff = .05;
# Don't show rows that have no changes shown
my $excludeNoShow = 0;
# Don't show rows that have no changes highlighted.
my $excludeNoHighlight = 0;

my $Input1 = 0;
my $Input2 = 0;

my $usage = "You should specify two filenames\n\n";
$usage .= "Usage: ./HTMLColDiff.pl [-t showThreshold] [-T highlightThreshold] [-A absDiff] [-x] [-X] report.nightly.txt.a report.nightly.txt.b\n\n";
$usage .= "Where showThreshold and highlightThreshold are the amount of change needed to a value to be shown or highlighted resp. (in percent) and absDiff is the minimum amount of absolute difference for a highlight. ";
$usage .= "When -x is specified, any rows that have no changes shown (per the -t option) are excluded. When -X is specified, any rows that have no highlights (per the -T options) are excluded.\n\n";
$usage .= "The default options are -t $showThreshold -T $highlightThreshold -A $highlightAbsDiff\n";

while (@ARGV) {
  if ($ARGV[0] eq "-t") {
    shift;
    $showThreshold = int($ARGV[0]);
  } elsif ($ARGV[0] eq "-T") {
    shift;
    $highlightThreshold = int($ARGV[0]);
  } elsif ($ARGV[0] eq "-A") {
    shift;
    $highlightAbsDiff = $ARGV[0];
  } elsif ($ARGV[0] eq "-x") {
    $excludeNoShow = 1;
  } elsif ($ARGV[0] eq "-X") {
    $excludeNoHighlight = 1;
  } else {
    if (!$Input1) {
      $Input1 = $ARGV[0];
    } elsif (!$Input2) {
      $Input2 = $ARGV[0];
    } else {
      warn("Extra filename found: " . $ARGV[0]); 
    }
  }
  shift;
}

if (!$Input1 || !$Input2) {
  warn($usage);
  exit 1;
}

open(INPUT1, $Input1) or die "Couldn't open '$Input1'!";
open(INPUT2, $Input2) or die "Couldn't open '$Input2'!";

# Read all of the lines of both files into arrays:
my @File1 = <INPUT1>;
my @File2 = <INPUT2>;

# Convert the first file from an array of lines to a hash from the key to the
# whole line.
my %File1Map;
foreach my $Line (@File1) {
  my $Key = (split /[\s|]+/, $Line, 2)[0];
  $File1Map{$Key} = $Line;
  #print "Map '$Key' => '$Line'\n";
}

print("<p>Showing differences between $Input1 and $Input2</p>");
print("<p>");
if ($showThreshold == 0) {
  print "Showing all changes. ";
} else {
  print "Hiding changes smaller than $showThreshold%. ";
}
print "Highlighting changes larger than $highlightThreshold%.";
print "</p>\n";
if ($excludeNoHighlight) {
  print ("<p>Excluding rows that have no highlighted cells</p>\n");
} elsif ($excludeNoShow) {
  print ("<p>Excluding rows that have no significant difference</p>\n");
}

print "<table border='0' cellspacing='0' cellpadding='0'>\n";

# Loop over the second file, outputting it, surrounding field with <B> tags if
# they differ from the first file.

my $LineNo = -1;
foreach my $Line (@File2) {
  # Try to remove spaces from the headers. This is a bit of a hack, really...
  $Line =~ s/([^ ]) (codegen|compile)/$1\&nbsp;$2/g;

  my @Fields = split /([\s|]+)/, $Line;  # Keep the seperators as well...
  my $Key = $Fields[0];
  my $CompareLine = $File1Map{$Key};

  # Try to remove spaces from the headers. This is a bit of a hack, really...
  $CompareLine =~ s/([^ ]) (codegen|compile)/$1&nbsp;$2/g;

  my @FieldsCompare = split /[\s|]+/, $CompareLine;  # Do not keep seperators

  # Loop over all of the Fields, outputting them with an optional tag...
  my $FieldNo = 0;

  # Give the header row a different colour and then alternate betwen
  # grey and white every two rows.
  my $RowColour;
  if ($LineNo == -1) {
    $RowColour = "#FFCC99";
  } elsif (($LineNo / 2) % 2) {
    $RowColour = "#CCCCCC";
  } else {
    $RowColour = "#FFFFFF";
  }
  my $row = "<tr bgcolor=\"$RowColour\"><td>";
  my $showCells = 0;
  my $highlightCells = 0;
  foreach my $Field (@Fields) {
    if ($Field =~ /[\s|]+/) {    # If it's a seperator, just output it
      #print $Field;
      $row .= "</td><td>";
    } else {                  # If it's not a seperator, diff it...
      my $Show      = 0;
      my $Highlight = 0;
      my $Colour    = 0;

      if (@FieldsCompare > $FieldNo) {
        my $FieldComp = $FieldsCompare[$FieldNo];
        if ($Field =~ /^[0-9.]+$/ && $FieldComp =~ /^[0-9.]+$/ &&
            $FieldComp != 0 && $Field ne $FieldComp) {              # Handle numbers special

          # How much did the field change?
          my $Change = $Field/$FieldComp;

          # Check to see if the change is really small, don't show it
          # then.
          $Show = 1 if ($Change > 1 + ($showThreshold / 100)
                        || $Change < 1 - ($showThreshold / 100));

          # Highlight the change if it is large enough, both relatively
          # and absolutely
          $Highlight = 1 if ($Change > 1 + ($highlightThreshold / 100)
                           || $Change < 1 - ($highlightThreshold / 100));
          $Highlight = 0 if (abs($Field - $FieldComp) < $highlightAbsDiff);
          
          # Show and colour changes if the change is large enough
          if ($Show) {
            my $Percent = sprintf("%+.2f%%", ($Change-1)*100);
            $Field = "$FieldComp => $Field ($Percent)";
            $Colour = ($Change > 1 ? "red" : "green");
          }
          
        } elsif ($Field ne $FieldComp) {
          $Show    = 1;
          # Specially handle tests that are failing to compile but were not
          # doing so previously
          if ($Field eq "*") {
            $Highlight = 1;
            $Colour = "red";
            $Field = "FAIL";
          }
          # Always show but never highlight other changes in non-numeric
          # fields
          $Field = "$FieldComp => $Field";
        }
      }
      # Remove spaces, we don't want wrapping inside cells
      $Field =~ s/ /\&nbsp;/g;
      $row .= "<b><u>" if $Highlight;
      $row .= "<font color=\"$Colour\">" if $Colour;
      $row .= $Field;
      $row .= "</font>" if $Colour;
      $row .= "</u></b>" if $Highlight;
    

      # Keep track that at least one cell was shown/highlighted in this
      # row.
      $highlightCells = 1 if ($Highlight);
      $showCells = 1 if ($Show);

      $FieldNo++;
    }
  }
  $row .= "</td></tr>\n";
  # Always show the first row, but exclude rows that don't have any
  # changes or highlights if those options are enabled.
  if ($LineNo == -1 || (!$excludeNoHighlight || $highlightCells) && (!$excludeNoShow || $showCells)) {
    print $row;
    $LineNo++;
  }
}
print "</table>\n";