[tools] testbot: Allow specifying extra mission capabilities.

Francois Gouget fgouget at codeweavers.com
Wed Mar 4 09:30:11 CST 2020


This allows specifying extra builds or locales that a VM can handle,
without having these used for every mailing list patch or WineTest run.
The extra capabilities can then be used when manually scheduling a job
on the TestBot.

Wine-Bug: https://bugs.winehq.org/show_bug.cgi?id=47853
Signed-off-by: Francois Gouget <fgouget at codeweavers.com>
---

This patch requires updating the database schema by applying 
update42.sql. Note that the new MissionCaps field is defined as NOT NULL 
and in my tests mysql initialized it to empty strings.

The patch also requires restarting the web server and TestBot Engine.

 testbot/ddl/update42.sql            |  5 +++++
 testbot/ddl/winetestbot.sql         |  1 +
 testbot/doc/winetestbot-schema.dia  | 23 +++++++++++++++++++++++
 testbot/lib/WineTestBot/Missions.pm | 26 ++++++++++++++++++++++++--
 testbot/lib/WineTestBot/VMs.pm      | 10 +++++++++-
 testbot/web/Submit.pl               |  2 +-
 testbot/web/admin/VMDetails.pl      |  3 ++-
 7 files changed, 65 insertions(+), 5 deletions(-)
 create mode 100644 testbot/ddl/update42.sql

diff --git a/testbot/ddl/update42.sql b/testbot/ddl/update42.sql
new file mode 100644
index 0000000000..f38833e3da
--- /dev/null
+++ b/testbot/ddl/update42.sql
@@ -0,0 +1,5 @@
+USE winetestbot;
+
+ALTER TABLE VMs
+  ADD MissionCaps VARCHAR(512) NOT NULL
+      AFTER Missions;
diff --git a/testbot/ddl/winetestbot.sql b/testbot/ddl/winetestbot.sql
index e6114e0917..e1cb5714f3 100644
--- a/testbot/ddl/winetestbot.sql
+++ b/testbot/ddl/winetestbot.sql
@@ -49,6 +49,7 @@ CREATE TABLE VMs
   Type          ENUM('win32', 'win64', 'build', 'wine') NOT NULL,
   Role          ENUM('extra', 'base', 'winetest', 'retired', 'deleted') NOT NULL,
   Missions      VARCHAR(256)     NOT NULL,
+  MissionCaps   VARCHAR(512)     NOT NULL,
   Status        ENUM('dirty', 'reverting', 'sleeping', 'idle', 'running', 'off', 'offline', 'maintenance') NOT NULL,
   Errors        INT(2)           NULL,
   ChildPid      INT(5)           NULL,
diff --git a/testbot/doc/winetestbot-schema.dia b/testbot/doc/winetestbot-schema.dia
index 372d3bf006..81ab656b7f 100644
--- a/testbot/doc/winetestbot-schema.dia
+++ b/testbot/doc/winetestbot-schema.dia
@@ -2406,6 +2406,29 @@
             <dia:string>##</dia:string>
           </dia:attribute>
         </dia:composite>
+        <dia:composite type="table_attribute">
+          <dia:attribute name="name">
+            <dia:string>#MissionCaps#</dia:string>
+          </dia:attribute>
+          <dia:attribute name="type">
+            <dia:string>#VARCHAR(512)#</dia:string>
+          </dia:attribute>
+          <dia:attribute name="comment">
+            <dia:string>##</dia:string>
+          </dia:attribute>
+          <dia:attribute name="primary_key">
+            <dia:boolean val="false"/>
+          </dia:attribute>
+          <dia:attribute name="nullable">
+            <dia:boolean val="false"/>
+          </dia:attribute>
+          <dia:attribute name="unique">
+            <dia:boolean val="false"/>
+          </dia:attribute>
+          <dia:attribute name="default_value">
+            <dia:string>##</dia:string>
+          </dia:attribute>
+        </dia:composite>
         <dia:composite type="table_attribute">
           <dia:attribute name="name">
             <dia:string>#Status#</dia:string>
diff --git a/testbot/lib/WineTestBot/Missions.pm b/testbot/lib/WineTestBot/Missions.pm
index 4f8387542f..810eb4dda4 100644
--- a/testbot/lib/WineTestBot/Missions.pm
+++ b/testbot/lib/WineTestBot/Missions.pm
@@ -142,9 +142,10 @@ sub GetTaskMissionDescription($$)
   return $Description;
 }
 
-sub GetMissionCaps($)
+sub GetMissionCaps($$)
 {
-  my ($MissionStatement) = @_;
+  my ($MissionStatement, $MissionCaps) = @_;
+
   my $Capabilities = { build => {}, lang => {} };
 
   # Extract capabilities from the mission statement
@@ -165,6 +166,27 @@ sub GetMissionCaps($)
       }
     }
   }
+
+  # Parse the additional capabilities
+  foreach my $Capability (split /,/, $MissionCaps || "")
+  {
+    if ($Capability =~ s/^lang=//)
+    {
+      foreach my $Lang (split /[|]/, $Capability)
+      {
+        $Capabilities->{lang}->{$Lang} = 1;
+      }
+    }
+    elsif ($Capability =~ /^(?:win32|wow32|wow64)$/)
+    {
+      $Capabilities->{build}->{$Capability} = 1;
+    }
+    else
+    {
+      $ErrMessage ||= "Invalid option capability '$Capability'";
+    }
+  }
+
   if (%{$Capabilities->{lang}})
   {
     # en_US is the default for Wine VMs and must always be supported
diff --git a/testbot/lib/WineTestBot/VMs.pm b/testbot/lib/WineTestBot/VMs.pm
index 6c3c8b759f..6dd1ff2bb1 100644
--- a/testbot/lib/WineTestBot/VMs.pm
+++ b/testbot/lib/WineTestBot/VMs.pm
@@ -311,6 +311,7 @@ sub ResetModified($)
   $self->SUPER::ResetModified();
   $self->{OldType} = $self->Type;
   $self->{OldMissions} = $self->Missions;
+  $self->{OldMissionCaps} = $self->MissionCaps;
 }
 
 my $_SupportedMissions = {
@@ -347,7 +348,8 @@ sub Validate($)
     return ("Role", "Only win32, win64 and wine VMs can have a role of '" . $self->Role . "'");
   }
   if ($self->ValuesDiffer($self->{OldType}, $self->Type) or
-      $self->ValuesDiffer($self->{OldMissions}, $self->Missions))
+      $self->ValuesDiffer($self->{OldMissions}, $self->Missions) or
+      $self->ValuesDiffer($self->{OldMissionCaps}, $self->MissionCaps))
   {
     my ($ErrMessage, $Missions) = ParseMissionStatement($self->Missions);
     return ("Missions", $ErrMessage) if (defined $ErrMessage);
@@ -366,8 +368,13 @@ sub Validate($)
         }
       }
     }
+
+    ($ErrMessage, my $_Caps) = GetMissionCaps("", $self->MissionCaps);
+    return ("MissionCaps", $ErrMessage) if (defined $ErrMessage);
+
     $self->{OldType} = $self->Type;
     $self->{OldMissions} = $self->Missions;
+    $self->{OldMissionCaps} = $self->MissionCaps;
   }
 
   return $self->SUPER::Validate();
@@ -734,6 +741,7 @@ my @PropertyDescriptors = (
   CreateEnumPropertyDescriptor("Type", "Type of VM", !1, 1, ['win32', 'win64', 'build', 'wine']),
   CreateEnumPropertyDescriptor("Role", "VM Role", !1, 1, ['extra', 'base', 'winetest', 'retired', 'deleted']),
   CreateBasicPropertyDescriptor("Missions", "Missions", !1, 1, "A", 256),
+  CreateBasicPropertyDescriptor("MissionCaps", "Mission Capabilities", !1, !1, "A", 512),
   CreateEnumPropertyDescriptor("Status", "Current status", !1, 1, ['dirty', 'reverting', 'sleeping', 'idle', 'running', 'off', 'offline', 'maintenance']),
   CreateBasicPropertyDescriptor("Errors", "Errors", !1, !1, "N", 2),
   CreateBasicPropertyDescriptor("ChildPid", "Child process id", !1, !1, "N", 5),
diff --git a/testbot/web/Submit.pl b/testbot/web/Submit.pl
index f76ca6e1af..5e9a61e7c3 100644
--- a/testbot/web/Submit.pl
+++ b/testbot/web/Submit.pl
@@ -484,7 +484,7 @@ sub _initialize($$$)
   foreach my $VMKey (@$SortedKeys)
   {
     my $VM = $VMs->GetItem($VMKey);
-    my ($ErrMessage, $Caps) = GetMissionCaps($VM->Missions);
+    my ($ErrMessage, $Caps) = GetMissionCaps($VM->Missions, $VM->MissionCaps);
     LogMsg "$ErrMessage\n" if (defined $ErrMessage);
 
     my @Builds = $VM->Type eq "wine" ? keys %{$Caps->{build}} : ("vm");
diff --git a/testbot/web/admin/VMDetails.pl b/testbot/web/admin/VMDetails.pl
index 095de3a1eb..27ffd2f382 100644
--- a/testbot/web/admin/VMDetails.pl
+++ b/testbot/web/admin/VMDetails.pl
@@ -74,7 +74,7 @@ sub GenerateFooter($)
   print "<thead><tr><th class='Record'>Legend</th></tr></thead>\n";
   print "<tbody><tr><td class='Record'>\n";
 
-  print "<p>The Missions syntax is <i>mission1:mission2:...|mission3|...</i> where <i>mission1</i> and <i>mission2</i> will be run in the same task, and <i>mission3</i> in a separate task.<br>\n";
+  print "<p>The <b>Missions</b> syntax is <i>mission1:mission2:...|mission3|...</i> where <i>mission1</i> and <i>mission2</i> will be run in the same task, and <i>mission3</i> in a separate task.<br>\n";
   print "Each mission is composed of a build and options separated by commas: <i>build,option1=value,option2,...</i>. The value can be omitted for boolean options and defaults to true.<br>\n";
   print "The supported builds are <i>build</i> for build VMs; <i>exe32</i> and <i>exe64</i> for Windows VMs;<i> win32</i>, <i>wow32</i> and <i>wow64</i> for Wine VMs.</p>\n";
   print "<p>On Wine VMs:<br>\n";
@@ -82,6 +82,7 @@ sub GenerateFooter($)
   print "The <i>lang</i> option can be set to run the tests in the specified \$LANG locale. The default is en_US (<i>.UTF-8</i> can be omitted).<br>\n";
   print "The <i>dir</i> option can be set to specify the directory in which to run the tests. A path starting with a single letter followed by a slash specifies the drive, for instance 'c/' for 'c:' (the default).<br>\n";
   print "If set, the <i>nosubmit</i> option specifies that the WineTest results should not be published online.</p>\n";
+  print "<p>The <b>MissionCaps</b> syntax is <i>option1,option2=value1|value2,...</i> where <i>option1</i> is either a build or an option name, and <i>option2</i> is the name of an option that can be set to either <i>value1</i> or <i>value2</i>.<br>\n";
   print "</td></tr></tbody>\n";
   print "</table></div>\n";
   $self->SUPER::GenerateFooter();
-- 
2.20.1



More information about the wine-devel mailing list