Signed-off-by: Francois Gouget fgouget@codeweavers.com --- testbot/web/JobDetails.pl | 378 +++++++++++++++++++++----------------- 1 file changed, 205 insertions(+), 173 deletions(-)
diff --git a/testbot/web/JobDetails.pl b/testbot/web/JobDetails.pl index 5b8b7013a..c4d6b1a1b 100644 --- a/testbot/web/JobDetails.pl +++ b/testbot/web/JobDetails.pl @@ -2,7 +2,7 @@ # Job details page # # Copyright 2009 Ge van Geldorp -# Copyright 2012-2014,2017-2020 Francois Gouget +# Copyright 2012-2014,2017-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 @@ -20,73 +20,35 @@
use strict;
-package JobDetailsPage; +package StepsTasksBlock;
-use ObjectModel::CGI::CollectionPage; -our @ISA = qw(ObjectModel::CGI::CollectionPage); +use ObjectModel::CGI::CollectionBlock; +our @ISA = qw(ObjectModel::CGI::CollectionBlock);
-use File::Basename; -use POSIX qw(strftime); use URI::Escape; +use POSIX qw(strftime);
-use WineTestBot::Config; -use WineTestBot::Jobs; -use WineTestBot::Log; # For Elapsed() -use WineTestBot::LogUtils; -use WineTestBot::Missions; -use WineTestBot::StepsTasks; use WineTestBot::Utils; +use WineTestBot::Missions; use WineTestBot::Engine::Notify;
-sub _initialize($$$) +sub Create($$) { - my ($self, $Request, $RequiredRole) = @_; - $self->{start} = Time(); + my ($Collection, $EnclosingPage) = @_;
- my $JobId = $self->GetParam("Key"); - if (! defined($JobId)) - { - $JobId = $self->GetParam("JobId"); - } - $self->{Job} = CreateJobs()->GetItem($JobId); - if (!defined $self->{Job}) - { - exit($self->Redirect("/")); - } - $self->{JobId} = $JobId; - - $self->SUPER::_initialize($Request, $RequiredRole, CreateStepsTasks(undef, $self->{Job})); - if ($self->{Job}->Status =~ /^(?:queued|running)$/) - { - $self->SetRefreshInterval(30); - } -} - -sub GetPageTitle($) -{ - my ($self) = @_; - - my $PageTitle = $self->{Job}->Remarks; - $PageTitle =~ s/^[[]\Q$PatchesMailingList\E[]] //; - $PageTitle = "Job " . $self->{JobId} if ($PageTitle eq ""); - $PageTitle .= " - ${ProjectName} Test Bot"; - return $PageTitle; + return StepsTasksBlock->new($Collection, $EnclosingPage); }
-sub GetTitle($) -{ - my ($self) = @_; - - return "Job " . $self->{JobId} . " - " . $self->{Job}->Remarks; -} +# +# Individual item property support +#
-sub DisplayProperty($$$) +sub DisplayProperty($$) { - my ($self, $CollectionBlock, $PropertyDescriptor) = @_; + my ($self, $PropertyDescriptor) = @_;
my $PropertyName = $PropertyDescriptor->GetName(); - return $PropertyName eq "StepNo" || $PropertyName eq "TaskNo" || $PropertyName eq "Status" || $PropertyName eq "VM" || $PropertyName eq "Timeout" || $PropertyName eq "FileName" || @@ -94,9 +56,22 @@ sub DisplayProperty($$$) $PropertyName eq "Ended" || $PropertyName eq "TestFailures"; }
-sub GenerateHeaderCell($$$) +sub SortKeys($$) { - my ($self, $CollectionBlock, $PropertyDescriptor) = @_; + my ($self, $Keys) = @_; + + my @SortedKeys = sort { $a <=> $b } @$Keys; + return @SortedKeys; +} + + +# +# Item cell generation +# + +sub GenerateHeaderCell($$) +{ + my ($self, $PropertyDescriptor) = @_;
my $PropertyName = $PropertyDescriptor->GetName(); if ($PropertyName eq "CmdLineArg") @@ -109,13 +84,104 @@ sub GenerateHeaderCell($$$) } else { - return $self->SUPER::GenerateHeaderCell($CollectionBlock, $PropertyDescriptor); + return $self->SUPER::GenerateHeaderCell($PropertyDescriptor); + } +} + +sub GenerateDataCell($$$$) +{ + my ($self, $StepTask, $PropertyDescriptor, $DetailsPage) = @_; + + my $PropertyName = $PropertyDescriptor->GetName(); + if ($PropertyName eq "VM") + { + print "<td><a href='#k", $self->escapeHTML($StepTask->GetKey()), "'>"; + print $self->escapeHTML($self->GetDisplayValue($StepTask, $PropertyDescriptor)); + print "</a></td>\n"; + } + elsif ($PropertyName eq "FileName") + { + my $FileName = $StepTask->GetFullFileName(); + if ($FileName and -r $FileName) + { + my $JobId = $self->{EnclosingPage}->GetJob()->Id; + my $URI = "/GetFile.pl?JobKey=" . uri_escape($JobId) . + "&StepKey=" . uri_escape($StepTask->StepNo); + print "<td><a href='" . $self->escapeHTML($URI) . "'>"; + print $self->escapeHTML($self->GetDisplayValue($StepTask, $PropertyDescriptor)); + print "</a></td>\n"; + } + else + { + $self->SUPER::GenerateDataCell($StepTask, $PropertyDescriptor, $DetailsPage); + } + } + elsif ($PropertyName eq "CmdLineArg") + { + my $Args = $self->escapeHTML($StepTask->CmdLineArg); + if ($Args eq "" or $StepTask->VM->Type eq "wine") + { + $Args .= "<br>" if ($Args ne ""); + my ($ErrMessage, $Missions) = ParseMissionStatement($StepTask->Missions); + if (defined $ErrMessage) + { + $Args .= "<span class='Mission'>$ErrMessage</span>"; + } + else + { + $Args .= "<span class='Mission'>". $self->escapeHTML(GetTaskMissionDescription($Missions->[0], $StepTask->Type)) ."</span>"; + } + } + print "<td>$Args</td>\n"; + } + elsif ($PropertyName eq "Ended") + { + if (defined $StepTask->Ended) + { + my $Duration = $StepTask->Ended - $StepTask->Started; + my $TagId = "E". $StepTask->Id; + print "<td><a id='$TagId' class='title' title='", + strftime("%Y-%m-%d %H:%M:%S", localtime($StepTask->Ended)), + "'>", DurationToString($Duration), "</a>\n"; + print "<script type='text/javascript'><!--\n"; + print " ShowDateTime(", $StepTask->Ended, ",'$TagId');\n"; + print "--></script>\n"; + print "</td>\n"; + } + else + { + print "<td> </td>\n"; + } + } + else + { + $self->SUPER::GenerateDataCell($StepTask, $PropertyDescriptor, $DetailsPage); } }
-sub GetItemActions($$) + +# +# Per-item actions handling +# + +sub GetItemActions($) { - #my ($self, $CollectionBlock) = @_; + #my ($self) = @_; + return []; +} + + +# +# Actions handling +# + +sub GetActions($) +{ + my ($self) = @_; + + # These are mutually exclusive + return ["Cancel job"] if (!defined $self->CanCancel()); + return ["Restart job"] if (!defined $self->CanRestart()); return []; }
@@ -123,20 +189,21 @@ sub CanCancel($) { my ($self) = @_;
- my $Status = $self->{Job}->Status; + my $Job = $self->{EnclosingPage}->GetJob(); + my $Status = $Job->Status; if ($Status ne "queued" && $Status ne "running") { - return "Job already $Status"; + return "Job already $Status"; }
- my $Session = $self->GetCurrentSession(); + my $Session = $self->{EnclosingPage}->GetCurrentSession(); if (! defined($Session)) { return "You are not authorized to cancel this job"; } my $CurrentUser = $Session->User; if (! $CurrentUser->HasRole("admin") && - $self->{Job}->User->GetKey() ne $CurrentUser->GetKey()) + $Job->User->GetKey() ne $CurrentUser->GetKey()) { return "You are not authorized to cancel this job"; } @@ -148,20 +215,21 @@ sub CanRestart($) { my ($self) = @_;
- my $Status = $self->{Job}->Status; + my $Job = $self->{EnclosingPage}->GetJob(); + my $Status = $Job->Status; if ($Status ne "boterror" && $Status ne "canceled") { return "Not a failed / canceled Job"; }
- my $Session = $self->GetCurrentSession(); + my $Session = $self->{EnclosingPage}->GetCurrentSession(); if (! defined($Session)) { return "You are not authorized to restart this job"; } my $CurrentUser = $Session->User; if (! $CurrentUser->HasRole("admin") && - $self->{Job}->User->GetKey() ne $CurrentUser->GetKey()) # FIXME: Admin only? + $Job->User->GetKey() ne $CurrentUser->GetKey()) # FIXME: Admin only? { return "You are not authorized to restart this job"; } @@ -169,35 +237,26 @@ sub CanRestart($) return undef; }
-sub GetActions($$) -{ - my ($self, $CollectionBlock) = @_; - - # These are mutually exclusive - return ["Cancel job"] if (!defined $self->CanCancel()); - return ["Restart job"] if (!defined $self->CanRestart()); - return []; -} - sub OnCancel($) { my ($self) = @_;
my $ErrMessage = $self->CanCancel(); - if (defined($ErrMessage)) + if (defined $ErrMessage) { - $self->{ErrMessage} = $ErrMessage; + $self->{EnclosingPage}->SetError(undef, $ErrMessage); return !1; }
- $ErrMessage = JobCancel($self->{JobId}); - if (defined($ErrMessage)) + my $JobId = $self->{EnclosingPage}->GetJob()->Id; + $ErrMessage = JobCancel($JobId); + if (defined $ErrMessage) { - $self->{ErrMessage} = $ErrMessage; + $self->{EnclosingPage}->SetError(undef, $ErrMessage); return !1; }
- exit($self->Redirect("/JobDetails.pl?Key=" . $self->{JobId})); + exit($self->{EnclosingPage}->Redirect("/JobDetails.pl?Key=$JobId")); }
sub OnRestart($) @@ -205,44 +264,89 @@ sub OnRestart($) my ($self) = @_;
my $ErrMessage = $self->CanRestart(); - if (defined($ErrMessage)) + if (defined $ErrMessage) { - $self->{ErrMessage} = $ErrMessage; + $self->{EnclosingPage}->SetError(undef, $ErrMessage); return !1; }
- $ErrMessage = JobRestart($self->{JobId}); - if (defined($ErrMessage)) + my $JobId = $self->{EnclosingPage}->GetJob()->Id; + $ErrMessage = JobRestart($JobId); + if (defined $ErrMessage) { - $self->{ErrMessage} = $ErrMessage; + $self->{EnclosingPage}->SetError(undef, $ErrMessage); return !1; }
- exit($self->Redirect("/JobDetails.pl?Key=" . $self->{JobId})); + exit($self->{EnclosingPage}->Redirect("/JobDetails.pl?Key=$JobId")); }
-sub OnAction($$$) +sub OnAction($$) { - my ($self, $CollectionBlock, $Action) = @_; + my ($self, $Action) = @_;
- if ($Action eq "Cancel job") - { - return $self->OnCancel(); - } - elsif ($Action eq "Restart job") + return $Action eq "Cancel job" ? $self->OnCancel() : + $Action eq "Restart job" ? $self->OnRestart() : + $self->SUPER::OnAction($Action); +} + + +package JobDetailsPage; + +use ObjectModel::CGI::SimpleCollectionPage; +our @ISA = qw(ObjectModel::CGI::SimpleCollectionPage); + +use URI::Escape; + +use WineTestBot::Config; +use WineTestBot::Jobs; +use WineTestBot::Log; # For Elapsed() +use WineTestBot::LogUtils; +use WineTestBot::StepsTasks; + + +sub _initialize($$$) +{ + my ($self, $Request, $RequiredRole) = @_; + $self->{start} = Time(); + + $self->{JobId} = $self->GetParam("Key"); + $self->{JobId} = $self->GetParam("JobId") if (!defined $self->{JobId}); + + $self->{Job} = CreateJobs()->GetItem($self->{JobId}); + exit($self->Redirect("/")) if (!defined $self->{Job}); + + my $Collection = CreateStepsTasks(undef, $self->{Job}); + $self->SUPER::_initialize($Request, $RequiredRole, $Collection, &StepsTasksBlock::Create); + if ($self->{Job}->Status =~ /^(?:queued|running)$/) { - return $self->OnRestart(); + $self->SetRefreshInterval(30); } +} + +sub GetJob($) +{ + my ($self) = @_;
- return $self->SUPER::OnAction($CollectionBlock, $Action); + return $self->{Job}; }
-sub SortKeys($$$) +sub GetPageTitle($) { - my ($self, $CollectionBlock, $Keys) = @_; + my ($self) = @_;
- my @SortedKeys = sort { $a <=> $b } @$Keys; - return @SortedKeys; + my $PageTitle = $self->{Job}->Remarks; + $PageTitle =~ s/^[[]\Q$PatchesMailingList\E[]] //; + $PageTitle = "Job " . $self->{JobId} if ($PageTitle eq ""); + $PageTitle .= " - ${ProjectName} Test Bot"; + return $PageTitle; +} + +sub GetTitle($) +{ + my ($self) = @_; + + return "Job $self->{JobId} - ". $self->{Job}->Remarks; }
sub InitMoreInfo($) @@ -250,7 +354,7 @@ sub InitMoreInfo($) my ($self) = @_;
my $More = $self->{More} = {}; - my $Keys = $self->SortKeys(undef, $self->{Collection}->GetKeys()); + my $Keys = $self->{CollectionBlock}->SortKeys($self->{Collection}->GetKeys()); foreach my $Key (@$Keys) { my $StepTask = $self->{Collection}->GetItem($Key); @@ -458,7 +562,7 @@ function HideLog(event, url) EOF
print "<div class='Content'>\n"; - my $Keys = $self->SortKeys(undef, $self->{Collection}->GetKeys()); + my $Keys = $self->{CollectionBlock}->SortKeys($self->{Collection}->GetKeys()); my $KeyIndex = 0; foreach my $Key (@$Keys) { @@ -627,78 +731,6 @@ EOF print "</div>\n"; }
-sub GenerateDataCell($$$$$) -{ - my ($self, $CollectionBlock, $StepTask, $PropertyDescriptor, $DetailsPage) = @_; - - my $PropertyName = $PropertyDescriptor->GetName(); - if ($PropertyName eq "VM") - { - print "<td><a href='#k", $self->escapeHTML($StepTask->GetKey()), "'>"; - print $self->escapeHTML($self->GetDisplayValue($CollectionBlock, $StepTask, - $PropertyDescriptor)); - print "</a></td>\n"; - } - elsif ($PropertyName eq "FileName") - { - my $FileName = $StepTask->GetFullFileName(); - if ($FileName and -r $FileName) - { - my $URI = "/GetFile.pl?JobKey=" . uri_escape($self->{JobId}) . - "&StepKey=" . uri_escape($StepTask->StepNo); - print "<td><a href='" . $self->escapeHTML($URI) . "'>"; - print $self->escapeHTML($self->GetDisplayValue($CollectionBlock, $StepTask, - $PropertyDescriptor)); - print "</a></td>\n"; - } - else - { - $self->SUPER::GenerateDataCell($CollectionBlock, $StepTask, $PropertyDescriptor, $DetailsPage); - } - } - elsif ($PropertyName eq "CmdLineArg") - { - my $Args = $self->escapeHTML($StepTask->CmdLineArg); - if ($Args eq "" or $StepTask->VM->Type eq "wine") - { - $Args .= "<br>" if ($Args ne ""); - my ($ErrMessage, $Missions) = ParseMissionStatement($StepTask->Missions); - if (defined $ErrMessage) - { - $Args .= "<span class='Mission'>$ErrMessage</span>"; - } - else - { - $Args .= "<span class='Mission'>". $self->escapeHTML(GetTaskMissionDescription($Missions->[0], $StepTask->Type)) ."</span>"; - } - } - print "<td>$Args</td>\n"; - } - elsif ($PropertyName eq "Ended") - { - if (defined $StepTask->Ended) - { - my $Duration = $StepTask->Ended - $StepTask->Started; - my $TagId = "E". $StepTask->Id; - print "<td><a id='$TagId' class='title' title='", - strftime("%Y-%m-%d %H:%M:%S", localtime($StepTask->Ended)), - "'>", DurationToString($Duration), "</a>\n"; - print "<script type='text/javascript'><!--\n"; - print " ShowDateTime(", $StepTask->Ended, ",'$TagId');\n"; - print "--></script>\n"; - print "</td>\n"; - } - else - { - print "<td> </td>\n"; - } - } - else - { - $self->SUPER::GenerateDataCell($CollectionBlock, $StepTask, $PropertyDescriptor, $DetailsPage); - } -} - sub GenerateFooter($) { my ($self) = @_;