Francois Gouget : winetest/build-patterns: Add links to the test commits.
Alexandre Julliard
julliard at winehq.org
Thu May 6 14:55:12 CDT 2021
Module: tools
Branch: master
Commit: ebbd6ac838bd3ef7bd9261959983eb49f933ad33
URL: https://source.winehq.org/git/tools.git/?a=commit;h=ebbd6ac838bd3ef7bd9261959983eb49f933ad33
Author: Francois Gouget <fgouget at codeweavers.com>
Date: Thu May 6 14:23:00 2021 +0200
winetest/build-patterns: Add links to the test commits.
This provides a link to the most likely culprit when a test starts
failing.
Signed-off-by: Francois Gouget <fgouget at codeweavers.com>
Signed-off-by: Alexandre Julliard <julliard at winehq.org>
---
winetest/build-patterns | 149 +++++++++++++++++++++++++++++++++++++++++++++++-
1 file changed, 146 insertions(+), 3 deletions(-)
diff --git a/winetest/build-patterns b/winetest/build-patterns
index d16050d..eb152c8 100755
--- a/winetest/build-patterns
+++ b/winetest/build-patterns
@@ -31,7 +31,7 @@ sub BEGIN
}
unshift @INC, $1 if ($0 =~ m=^(/.*)/[^/]+$=);
}
-use vars qw/$workdir $gitdir $patternbuilds $fixed_threshold/;
+use vars qw/$workdir $gitdir $gitweb $patternbuilds $fixed_threshold/;
require "winetest.conf";
my $name0=$0;
@@ -249,6 +249,9 @@ my %reports;
# - name
# The uniquely identifying test name in the form 'module:unit'.
#
+# - source
+# The source file for that test unit.
+#
# - colors
# A hashtable of colors indexed by failure count.
#
@@ -303,6 +306,10 @@ my %reports;
#
# - status
# A hashtable of test results indexed by the build name.
+#
+# - commits
+# A hashtable of the commit objects, indexed first buy build name and then
+# by commit id.
my %tests;
foreach my $build (@sortedbuilds)
@@ -339,7 +346,7 @@ foreach my $build (@sortedbuilds)
while (my $line = <$fh>)
{
chomp $line;
- my ($testname, $_source, @items) = split / /, $line;
+ my ($testname, $source, @items) = split / /, $line;
if ($testname !~ /:/)
{
error("found an invalid test unit name ($testname) in '$filename'\n");
@@ -347,7 +354,13 @@ foreach my $build (@sortedbuilds)
}
$build->{hastest}->{$testname} = 1;
my $test = $tests{$testname};
- $tests{$testname} = $test = { name => $testname } if (!$test);
+ if (!$test)
+ {
+ $tests{$testname} = $test = {
+ name => $testname,
+ source => $source,
+ };
+ }
foreach my $statreps (@items)
{
@@ -604,6 +617,80 @@ foreach my $testname (keys %tests)
}
+#
+# Collect the related commits
+#
+
+# A hashtable of commit objects indexed by their Git commit id.
+# Each object has the following fields:
+#
+# - index
+# An integer recording the commit order, with 0 for the newest commit and
+# negative numbers for the others.
+#
+# - id
+# The Git commit id.
+#
+# - build
+# The Git commit id of the first build after this commit.
+#
+# - summary
+# The commit summary.
+my %commits;
+
+# A hashtable mapping filenames to a set of matching commit objects indexed by
+# Git commit id.
+my %path2commits;
+
+my $cmd = "git log --pretty=oneline --name-status $sortedbuilds[0]->{name}^..$sortedbuilds[-1]->{name}";
+if (open(my $fh, "-|", $cmd))
+{
+ my $index = 0;
+ my ($commit, $build);
+ foreach my $line (<$fh>)
+ {
+ chomp $line;
+ if ($line =~ /^([0-9a-f]{40}) (.*)$/)
+ {
+ my ($commitid, $summary) = ($1, $2);
+ # The commits are returned in reverse chronological order. So the
+ # build commit comes first, then the commits that got into it.
+ $build = $builds{$commitid} if ($builds{$commitid});
+ if (!$build)
+ {
+ error("$commit does not belong to any build\n");
+ next;
+ }
+ $commits{$commitid} = $commit = {
+ index => $index--,
+ id => $commitid,
+ build => $build,
+ summary => $summary,
+ };
+ }
+ elsif ($line =~ /^R[0-9]+\t(\S+)\t(\S+)$/ or $line =~ /^.\t(\S+)$/)
+ {
+ my ($path1, $path2) = ($1, $2);
+ if (!$commit)
+ {
+ error("did not find a commit before: $line\n");
+ next;
+ }
+ foreach my $filename ($path1, $path2)
+ {
+ next if (!$filename);
+ $path2commits{$filename}->{$commit->{id}} = $commit;
+ }
+ }
+ else
+ {
+ error("found an unsupported line type in '$cmd' output: $line\n");
+ }
+ }
+ close($fh);
+}
+
+
#
# Compute color gradients
#
@@ -830,6 +917,54 @@ sub write_pattern_line($$$)
print $html "</div> $label\n";
}
+sub index2symbol($)
+{
+ my ($index) = @_;
+ my @symbols = ("0".."9", "a".."z", "A".."Z");
+ return $symbols[$index % 62];
+}
+
+sub write_commits($$)
+{
+ my ($html, $test) = @_;
+
+ print $html "<div class='pattern'>";
+ my $i = 0;
+ my @symbuilds;
+ foreach my $build (@sortedbuilds)
+ {
+ if ($test->{commits}->{$build->{name}})
+ {
+ my $symbol = index2symbol($i++);
+ push @symbuilds, [$symbol, $build];
+ printf $html "<a title='%s'>%s</a>",
+ short_date($build->{date}), $symbol;
+ }
+ else
+ {
+ print $html " ";
+ }
+ }
+ print $html "</div> <i>← potentially related commits</i>\n";
+
+ if (@symbuilds)
+ {
+ print $html "\n";
+ foreach my $symbuild (@symbuilds)
+ {
+ my $first = 1;
+ my ($symbol, $build) = @$symbuild;
+ my $buildcommits = $test->{commits}->{$build->{name}};
+ foreach my $commit (sort { $a->{index} <=> $b->{index} } values %$buildcommits)
+ {
+ print $html $first ? "$symbol." : " ";
+ $first = undef;
+ printf $html " <a href='%s/commitdiff/%s' title='%s'>%s</a>\n", $gitweb, $commit->{id}, short_date($build->{date}), $commit->{summary};
+ }
+ }
+ }
+}
+
sub write_pattern($$$)
{
my ($html, $test, $pagereports) = @_;
@@ -843,6 +978,7 @@ sub write_pattern($$$)
next if (!$test->{testreports}->{$reportdir}->{failed});
write_pattern_line($html, $test, $reportdir);
}
+ write_commits($html, $test) if (%{$test->{commits}});
}
sub write_patterns_list($$$$)
@@ -917,6 +1053,7 @@ EOF
{
my $test = $tests{$testname};
$test->{colors} = {};
+ $test->{commits} = {};
my $first = @sortedbuilds;
my $last = -1;
@@ -965,6 +1102,12 @@ EOF
%{$test->{newmodes}} ? "newmode" :
"regular";
push @{$lists{$listid}->{testnames}}, $testname;
+
+ foreach my $commit (values %{$path2commits{$test->{source}}})
+ {
+ my $buildname = $commit->{build}->{name};
+ $test->{commits}->{$buildname}->{$commit->{id}} = $commit;
+ }
}
# Generate the lists index (and up test unit links)
More information about the wine-cvs
mailing list