[tools] winetest/build-patterns: Identify commits indirectly related to a test unit.

Francois Gouget fgouget at codeweavers.com
Tue May 11 11:07:43 CDT 2021


Some test units depend on files other than the main C source file such
as resource file, JavaScript source, etc. Patches modifying these files
could also impact the test results.
Also tests may fail in Wine because of modifications to the Wine module
rather than to the test.
So report patches to any of these components, but hide the more indirect
and numerous ones.

Signed-off-by: Francois Gouget <fgouget at codeweavers.com>
---
 winetest/build-patterns | 144 ++++++++++++++++++++++++++++++++--------
 winetest/report.css     |   9 +++
 2 files changed, 127 insertions(+), 26 deletions(-)

diff --git a/winetest/build-patterns b/winetest/build-patterns
index eb152c872..10cc0214c 100755
--- a/winetest/build-patterns
+++ b/winetest/build-patterns
@@ -312,6 +312,9 @@ my %reports;
 #     by commit id.
 my %tests;
 
+# A set containing the test units source files.
+my %testsources;
+
 foreach my $build (@sortedbuilds)
 {
     my $filename = "data/$build->{name}/testresults.txt";
@@ -360,6 +363,7 @@ foreach my $build (@sortedbuilds)
                 name => $testname,
                 source => $source,
             };
+            $testsources{$source} = 1;
         }
 
         foreach my $statreps (@items)
@@ -679,7 +683,34 @@ if (open(my $fh, "-|", $cmd))
             foreach my $filename ($path1, $path2)
             {
                 next if (!$filename);
-                $path2commits{$filename}->{$commit->{id}} = $commit;
+
+                if ($filename =~ m~((?:dlls|programs)/([^/]+))/tests/([^/]+)\.c$~)
+                {
+                    my ($moddir, $module, $unit) = ($1, $2, $3);
+                    if ($tests{"$module:$unit"})
+                    {
+                        $path2commits{$filename}->{$commit->{id}} = $commit;
+                    }
+                    else
+                    {
+                        # This C file is not the source for a test unit
+                        # so it could impact any test in that directory
+                        $path2commits{"$moddir/tests"}->{$commit->{id}} = $commit;
+                    }
+                }
+                elsif ($filename =~ m~((?:dlls|programs)/[^/]+)/tests/~)
+                {
+                    my $moddir = $1;
+                    # This is not not a C file so it could impact any test in
+                    # that directory
+                    $path2commits{"$moddir/tests"}->{$commit->{id}} = $commit;
+                }
+                elsif ($filename =~ m~((?:dlls|programs)/[^/]+)/~)
+                {
+                    my $moddir = $1;
+                    $path2commits{$moddir}->{$commit->{id}} = $commit;
+                }
+                # ignore changes to other files
             }
         }
         else
@@ -924,44 +955,85 @@ sub index2symbol($)
     return $symbols[$index % 62];
 }
 
+my %scope_descs = (
+    U => "Modifies this test",
+    t => "Modifies a test resource (maybe for another test)",
+    m => "Modifies the module",
+);
+
 sub write_commits($$)
 {
     my ($html, $test) = @_;
 
     print $html "<div class='pattern'>";
     my $i = 0;
-    my @symbuilds;
+    my (@udescs, @tmdescs);
     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
+        my $buildcommits = $test->{commits}->{$build->{name}};
+        if (!$buildcommits)
         {
             print $html " ";
+            next;
         }
-    }
-    print $html "</div> <i>← potentially related commits</i>\n";
 
-    if (@symbuilds)
-    {
-        print $html "\n";
-        foreach my $symbuild (@symbuilds)
+        my $symbol = index2symbol($i++);
+        my ($ucount, $tcount, $tmcount) = (0, 0, 0);
+        foreach my $commit (sort { $a->{index} <=> $b->{index} } values %$buildcommits)
         {
-            my $first = 1;
-            my ($symbol, $build) = @$symbuild;
-            my $buildcommits = $test->{commits}->{$build->{name}};
-            foreach my $commit (sort { $a->{index} <=> $b->{index} } values %$buildcommits)
+            my $scope = "m";
+            if ($path2commits{$test->{source}}->{$commit->{id}})
             {
-                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};
+                $scope = "U";
+            }
+            else
+            {
+                my $testdir = $test->{source};
+                $testdir =~ s~/[^/]+$~~;
+                if ($path2commits{$testdir}->{$commit->{id}})
+                {
+                    $scope = "t";
+                    $tcount++;
+                }
+            }
+
+            my $desc = sprintf(" <a class='commit%s' title='%s'>%s</a> <a href='%s/commitdiff/%s' title='%s'>%s</a>",
+                               $scope, $scope_descs{$scope}, $scope,
+                               $gitweb, $commit->{id},
+                               short_date($build->{date}),
+                               $commit->{summary});
+            if ($scope eq "U")
+            {
+                push @udescs, ($ucount ? "\n  " : "\n$symbol."), $desc;
+                $ucount++;
+            }
+            else
+            {
+                push @tmdescs, ($tmcount ? "  " : "$symbol."), $desc, "\n";
+                $tmcount++;
             }
         }
+        push @udescs, " <i>[+$tmcount in details]</i>" if ($ucount and $tmcount);
+
+        my @impacts;
+        push @impacts, "this test" if ($ucount);
+        push @impacts, "test resources" if ($tcount);
+        push @impacts, "the module" if ($tmcount > $tcount);
+        my $scope = $ucount ? "U" : $tcount ? "t" : "m";
+        my $count = $ucount + $tmcount;
+        printf $html "<a class='commit%s' title='%s : %s commit%s to %s'>%s</a>",
+                     $scope, short_date($build->{date}),
+                     $count, $count > 1 ? "s" : "",
+                     join(", ", @impacts), $symbol;
+    }
+    print $html "</div> <i>← potentially related commits</i>\n";
+
+    print $html @udescs if (@udescs);
+    if (@tmdescs)
+    {
+        print $html "<details><summary>Test and module patch details</summary>";
+        print $html @tmdescs;
+        print $html "</details>";
     }
 }
 
@@ -1012,6 +1084,18 @@ sub write_patterns_list($$$$)
     }
 }
 
+sub add_path_commits($$)
+{
+    my ($commits, $path) = @_;
+
+    return if (!$path2commits{$path});
+    foreach my $commit (values %{$path2commits{$path}})
+    {
+        my $buildname = $commit->{build}->{name};
+        $commits->{$buildname}->{$commit->{id}} = $commit;
+    }
+}
+
 sub write_patterns_page($$$)
 {
     my ($pagereports, $subpage, $title) = (@_);
@@ -1055,6 +1139,7 @@ EOF
         $test->{colors} = {};
         $test->{commits} = {};
 
+        my $has_wine_failures;
         my $first = @sortedbuilds;
         my $last = -1;
         my $fixed = 1;
@@ -1073,6 +1158,8 @@ EOF
                           $testreport->{first};
             $last = $replast if ($replast > $last);
 
+            $has_wine_failures ||= $reports{$reportdir}->{is_wine};
+
             for my $i (0.. at sortedbuilds-1)
             {
                 my $build = $sortedbuilds[$i];
@@ -1103,10 +1190,15 @@ EOF
                      "regular";
         push @{$lists{$listid}->{testnames}}, $testname;
 
-        foreach my $commit (values %{$path2commits{$test->{source}}})
+        add_path_commits($test->{commits}, $test->{source});
+        # Also take into account commits to test resources
+        my $moddir = $test->{source};
+        $moddir =~ s~/tests/[^/]+$~~;
+        add_path_commits($test->{commits}, "$moddir/tests");
+        if ($has_wine_failures)
         {
-            my $buildname = $commit->{build}->{name};
-            $test->{commits}->{$buildname}->{$commit->{id}} = $commit;
+            # In Wine any patch to the module could have caused the failures
+            add_path_commits($test->{commits}, $moddir);
         }
     }
 
diff --git a/winetest/report.css b/winetest/report.css
index 2cc466304..4c9197250 100644
--- a/winetest/report.css
+++ b/winetest/report.css
@@ -111,3 +111,12 @@ div.pattern :hover   { color: black; text-decoration: underline; }
 .patL { /* error while getting the test list */
     background-color: #80aaff;
 }
+
+.commitU {
+    font-weight: bold;
+}
+.committ {
+}
+.commitm {
+    font-style: italic;
+}
-- 
2.20.1



More information about the wine-devel mailing list