[tools 2/6] testbot/web: Add pages to add, edit and show known failures.

Francois Gouget fgouget at codeweavers.com
Wed Jun 15 11:21:32 CDT 2022


The pages allow everyone to see the known failures.
But only TestBot administrators can create and modify them.

Wine-Bug: https://bugs.winehq.org/show_bug.cgi?id=48912
Signed-off-by: Francois Gouget <fgouget at codeweavers.com>
---
The plan is for the failure details page to later show all tasks where
the failure was found. That would allow developers to compare the logs
for diagnosis.

Adding a known failure is a sensitive operation as it causes that
failure to essentially be ignored. This means if the regular expression
is too broad whole classes of failures could end up being ignored. So
for now only the TestBot administrators can add them.
Another option would be to allow anyone with a login to add them, or
allow adding them but requiring a validation step by a TestBot
administrator (a bit like when new users are added).
But I think that can wait until we see how this goes.
---
 testbot/lib/WineTestBot/CGI/PageBase.pm |   1 +
 testbot/lib/WineTestBot/Config.pm       |   6 +-
 testbot/web/FailureDetails.pl           | 119 ++++++++++++++++++
 testbot/web/FailuresList.pl             | 160 ++++++++++++++++++++++++
 testbot/web/WineTestBot.css             |   3 +
 5 files changed, 287 insertions(+), 2 deletions(-)
 create mode 100644 testbot/web/FailureDetails.pl
 create mode 100644 testbot/web/FailuresList.pl

diff --git a/testbot/lib/WineTestBot/CGI/PageBase.pm b/testbot/lib/WineTestBot/CGI/PageBase.pm
index d6f33e2ca..0486bbefc 100644
--- a/testbot/lib/WineTestBot/CGI/PageBase.pm
+++ b/testbot/lib/WineTestBot/CGI/PageBase.pm
@@ -521,6 +521,7 @@ EOF
     print "        <li><p><a href='/PatchesList.pl'>",
           ucfirst($PatchesMailingList), "</a></p></li>\n";
   }
+  print "        <li><p><a href='/FailuresList.pl'>Failures</a></p></li>\n";
 
   my $Session = $self->GetCurrentSession();
   if ($self->SessionActive())
diff --git a/testbot/lib/WineTestBot/Config.pm b/testbot/lib/WineTestBot/Config.pm
index 089d792c5..6f57995e8 100644
--- a/testbot/lib/WineTestBot/Config.pm
+++ b/testbot/lib/WineTestBot/Config.pm
@@ -31,7 +31,7 @@ use vars qw (@ISA @EXPORT @EXPORT_OK $UseSSL $LogDir $DataDir $BinDir
              $MaxVMsWhenIdle $WaitForBoot $SleepAfterBoot $SleepAfterRevert
              $VMToolTimeout $WaitForShutdown $MaxVMErrors $MaxTaskTries
              $AdminEMail $RobotEMail
-             $WinePatchToOverride $WinePatchCc
+             $WinePatchToOverride $WinePatchCc $WineBugUrl
              $ReconfigBuildTimeout $ExeBuildTimeout $ExeModuleTimeout
              $WineBuildTimeout $WineModuleTimeout $TimeoutMargin
              $SuiteTimeout $SingleTimeout $SingleAvgTime $MaxUnitSize
@@ -48,7 +48,7 @@ require Exporter;
              $MaxRunningVMs $MaxVMsWhenIdle $WaitForBoot $SleepAfterBoot
              $SleepAfterRevert $VMToolTimeout $WaitForShutdown
              $MaxVMErrors $MaxTaskTries $AdminEMail
-             $RobotEMail $WinePatchToOverride $WinePatchCc $SuiteTimeout
+             $RobotEMail $WinePatchToOverride $WinePatchCc $WineBugUrl
              $ReconfigBuildTimeout $ExeBuildTimeout $ExeModuleTimeout
              $WineBuildTimeout $WineModuleTimeout $TimeoutMargin
              $SuiteTimeout $SingleTimeout $SingleAvgTime $MaxUnitSize
@@ -85,6 +85,8 @@ sub PrependPaths(@)
   "wine" => "git://source.winehq.org/git/wine.git",
 );
 
+$WineBugUrl = "https://bugs.winehq.org/show_bug.cgi?id=";
+
 # See the ScheduleOnHost() documentation in lib/WineTestBot/Jobs.pm
 $MaxRevertingVMs = 1;
 $MaxRevertsWhileRunningVMs = 0;
diff --git a/testbot/web/FailureDetails.pl b/testbot/web/FailureDetails.pl
new file mode 100644
index 000000000..7cab1d2a6
--- /dev/null
+++ b/testbot/web/FailureDetails.pl
@@ -0,0 +1,119 @@
+# -*- Mode: Perl; perl-indent-level: 2; indent-tabs-mode: nil -*-
+# Failure details page
+#
+# Copyright 2022 Francois Gouget
+#
+# This library is free software; you can redistribute it and/or
+# modify it under the terms of the GNU Lesser General Public
+# License as published by the Free Software Foundation; either
+# version 2.1 of the License, or (at your option) any later version.
+#
+# This library is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+# Lesser General Public License for more details.
+#
+# You should have received a copy of the GNU Lesser General Public
+# License along with this library; if not, write to the Free Software
+# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
+
+use strict;
+
+package FailureDetailsPage;
+
+use ObjectModel::CGI::ItemPage;
+our @ISA = qw(ObjectModel::CGI::ItemPage);
+
+use WineTestBot::Config;
+use WineTestBot::Failures;
+
+
+sub _initialize($$$)
+{
+  my ($self, $Request, $RequiredRole) = @_;
+
+  $self->SUPER::_initialize($Request, $RequiredRole, CreateFailures());
+
+  my $Session = $self->GetCurrentSession();
+  if (!$Session or !$Session->User->HasRole("admin"))
+  {
+    # Only admin users can create and modify failures
+    exit($self->RedirectToParent()) if ($self->{Item}->GetIsNew());
+    $self->SetReadWrite(0);
+  }
+}
+
+sub DisplayProperty($$)
+{
+  my ($self, $PropertyDescriptor) = @_;
+
+  my $PropertyName = $PropertyDescriptor->GetName();
+  return # Already shown in the title
+         $PropertyName eq "Id" ? "" :
+         # Showing these makes no sense for new items since they are read-only
+         $PropertyName =~ /^(?:LastNew|LastOld|BugStatus|BugDescription)$/ ?
+                       ($self->{Item}->GetIsNew() ? "" : "ro") :
+         $self->SUPER::DisplayProperty($PropertyDescriptor);
+}
+
+sub GenerateValueView($$$$)
+{
+  my ($self, $PropertyDescriptor, $Value, $Format) = @_;
+
+  if ($PropertyDescriptor->GetName() =~ /^Bug(?:Id|Status|Description)$/)
+  {
+    print "<a href='$WineBugUrl", $self->{Item}->BugId, "' target='_blank'>",
+          $self->escapeHTML($Value || "Not fetched yet..."), "</a>";
+  }
+  else
+  {
+    $self->SUPER::GenerateValueView($PropertyDescriptor, $Value, $Format);
+  }
+}
+
+sub GenerateFooter($)
+{
+  my ($self) = @_;
+  print "<p></p><div class='CollectionBlock'><table>\n";
+  print "<thead><tr><th class='Record'>Legend</th></tr></thead>\n";
+  print "<tbody><tr><td>\n";
+
+  print "<p>The <b>Test module</b> is in fact the name of the error group the failure may occur in. Most of the time this is a test module but it may also be the name of the group containing the extra errors.<br>\n";
+  print "The <b>Test unit</b> is the name of the test unit the failure may occur in. For extra errors this should be an empty string.<br>\n";
+  print "The <b>Configurations RegExp</b> defines which test configurations are known to exhibit this failure. It should match the configuration names which are of the form <i>VM:logfile</i> where <i>VM</i> is the name of the virtual machine (which for Windows VMs includes the test configuration); and <i>logfile</i> is a task log file, the most important of which are the test reports: <i>exe32</i> or <i>exe64</i> for Windows, and <i>win32</i>, <i>wow32</i> or <i>wow64</i> for Wine. On Wine the log filename may contain test configuration information, typically the locale, in an underscore separated suffix.<br>\n";
+  print "The <b>Failures RegExp</b> should match the failure lines. Matching the test unit name is not necessary. Beware of the presence of wildcards in the error message such as: *+|()[]{}<br>\n";
+
+  print "</td></tr></tbody>\n";
+  print "</table></div>\n";
+  $self->SUPER::GenerateFooter();
+}
+
+sub OnAction($$)
+{
+  my ($self, $Action) = @_;
+
+  if ($Action eq "Save")
+  {
+    if (!$self->{RW})
+    {
+      $self->{ErrMessage} = "Only admin users can create or modify failures";
+      return 0;
+    }
+    if (($self->{Item}->BugId || "") ne $self->GetParam("BugId"))
+    {
+      $self->{Item}->BugStatus("");
+      $self->{Item}->BugDescription("");
+    }
+    return undef if (!$self->Save());
+    # FIXME Notify the TestBot Engine so it updates the bug information
+    exit($self->RedirectToParent());
+  }
+  return $self->SUPER::OnAction($Action);
+}
+
+
+package main;
+
+my $Request = shift;
+my $Page = FailureDetailsPage->new($Request, "");
+$Page->GeneratePage();
diff --git a/testbot/web/FailuresList.pl b/testbot/web/FailuresList.pl
new file mode 100644
index 000000000..f2608dc45
--- /dev/null
+++ b/testbot/web/FailuresList.pl
@@ -0,0 +1,160 @@
+# -*- Mode: Perl; perl-indent-level: 2; indent-tabs-mode: nil -*-
+# Known failures index page
+#
+# Copyright 2022 Francois Gouget
+#
+# This library is free software; you can redistribute it and/or
+# modify it under the terms of the GNU Lesser General Public
+# License as published by the Free Software Foundation; either
+# version 2.1 of the License, or (at your option) any later version.
+#
+# This library is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+# Lesser General Public License for more details.
+#
+# You should have received a copy of the GNU Lesser General Public
+# License along with this library; if not, write to the Free Software
+# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
+
+use strict;
+
+package FailuresBlock;
+
+use ObjectModel::CGI::CollectionBlock;
+our @ISA = qw(ObjectModel::CGI::CollectionBlock);
+
+use WineTestBot::Config;
+use WineTestBot::Failures;
+
+
+sub _initialize($$$)
+{
+  my ($self, $Collection, $EnclosingPage) = @_;
+
+  $self->SUPER::_initialize($Collection, $EnclosingPage);
+
+  my $Session = $EnclosingPage->GetCurrentSession();
+  if (!$Session or !$Session->User->HasRole("admin"))
+  {
+    $self->SetReadWrite(0);
+    # and hide the deleted entries
+    $self->{Collection}->AddFilter("BugStatus", ["deleted"], "<>");
+  }
+}
+
+sub Create($$)
+{
+  my ($Collection, $EnclosingPage) = @_;
+
+  return FailuresBlock->new($Collection, $EnclosingPage);
+}
+
+sub DisplayProperty($$)
+{
+  my ($self, $PropertyDescriptor) = @_;
+
+  my $PropertyName = $PropertyDescriptor->GetName();
+  return $PropertyName =~ /^(?:Notes|ConfigRegExp|FailureRegExp|BugId)$/ ? "" :
+         $self->SUPER::DisplayProperty($PropertyDescriptor);
+}
+
+sub GenerateHeaderView($$$)
+{
+  my ($self, $Row, $Col) = @_;
+
+  my $PropertyName = $Col->{Descriptor}->GetName();
+  if ($PropertyName eq "ErrorGroup")
+  {
+    print "<a class='title' title='or Error group'>Test module</a>";
+  }
+  else
+  {
+    $self->SUPER::GenerateHeaderView($Row, $Col);
+  }
+}
+
+sub GenerateDataView($$$)
+{
+  my ($self, $Row, $Col) = @_;
+
+  my $PropertyName = $Col->{Descriptor}->GetName();
+  if ($PropertyName =~ /^Test(?:Module|Unit)$/)
+  {
+    print "<a href='", $self->escapeHTML($self->GetDetailsLink($Row)), "'>",
+          $self->escapeHTML($Row->{Item}->$PropertyName), "</a>";
+  }
+  elsif ($PropertyName eq "BugStatus")
+  {
+    my $Status = $Row->{Item}->BugStatus || "Not fetched yet...";
+    my $Class = ($Status eq "Does not exist") ? "-missing" :
+                ($Status =~ /^(?:CLOSED|RESOLVED)/) ? "-closed" : "";
+    print "<span class='bug$Class'>", $self->escapeHTML($Status), "</span>";
+  }
+  elsif ($PropertyName eq "BugId")
+  {
+    print "<a href='$WineBugUrl", $Row->{Item}->BugId, "' target='_blank'>",
+          $self->escapeHTML($Row->{Item}->BugId), "</a>";
+  }
+  elsif ($PropertyName eq "BugDescription")
+  {
+    my $Value = $Row->{Item}->BugDescription || "Not fetched yet...";
+    my $Tooltip ="";
+    if ($Row->{Item}->Notes)
+    {
+      $Tooltip = " title='". $self->escapeHTML($Row->{Item}->Notes) ."'";
+    }
+    print "<a href='", $self->escapeHTML($self->GetDetailsLink($Row)),
+          "'$Tooltip>", $self->escapeHTML($Value), "</a>";
+  }
+  else
+  {
+    $self->SUPER::GenerateDataView($Row, $Col);
+  }
+}
+
+sub GetItemActions($)
+{
+  my ($self) = @_;
+
+  return ["Delete", "Restore"];
+}
+
+sub OnItemAction($$$)
+{
+  my ($self, $Failure, $Action) = @_;
+
+  if ($self->{RW})
+  {
+    return 1 if ($Action eq "Restore" and $Failure->BugStatus ne "deleted");
+
+    my $NewStatus = $Action eq "Delete" ? "deleted" :
+                    $Action eq "Restore" ? "unknown" :
+                    undef;
+    if ($NewStatus)
+    {
+      $Failure->BugStatus($NewStatus);
+      my ($_ErrProperty, $ErrMessage) = $Failure->Save();
+      if (defined $ErrMessage)
+      {
+        # Setting ErrField is only useful on form pages
+        $self->{EnclosingPage}->SetError(undef, $ErrMessage);
+        return 0;
+      }
+      # FIXME Notify the TestBot Engine so it updates the bug information
+      return 1;
+    }
+  }
+
+  return $self->SUPER::OnItemAction($Failure, $Action);
+}
+
+
+package main;
+
+use ObjectModel::CGI::CollectionPage;
+use WineTestBot::Failures;
+
+my $Request = shift;
+my $Page = ObjectModel::CGI::CollectionPage->new($Request, "", CreateFailures(), \&FailuresBlock::Create);
+$Page->GeneratePage();
diff --git a/testbot/web/WineTestBot.css b/testbot/web/WineTestBot.css
index fd6fca359..5e0c39ff4 100644
--- a/testbot/web/WineTestBot.css
+++ b/testbot/web/WineTestBot.css
@@ -407,6 +407,9 @@ pre
 .log-new { color: #e56e00; font-weight: bold; }
 .log-fullnew { color: red; font-weight: bold; }
 
+.bug-missing { color: red; font-weight: bold; }
+.bug-closed { color: red; }
+
 a.title { color:inherit; text-decoration: none; }
 a.tipdatetime { color:inherit; text-decoration: none; }
 a.timetipdate { color:inherit; text-decoration: none; }
-- 
2.30.2




More information about the wine-devel mailing list