Wine-Devel
By thread
wine-devel@list.winehq.org
By month
Messages by month
- ----- 2026 -----
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2025 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2024 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2023 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2022 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2021 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2020 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2019 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2018 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2017 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2016 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2015 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2014 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2013 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2012 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2011 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2010 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2009 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2008 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2007 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2006 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2005 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2004 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2003 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2002 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2001 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
June 2018
- 68 participants
- 1149 messages
[PATCH 3/5] schedsvc: Minor cleanup.
by Dmitry Timoshkov
Signed-off-by: Dmitry Timoshkov <dmitry(a)baikal.ru>
---
dlls/schedsvc/atsvc.c | 8 ++++----
1 file changed, 4 insertions(+), 4 deletions(-)
diff --git a/dlls/schedsvc/atsvc.c b/dlls/schedsvc/atsvc.c
index b8adc7279d..df4185eac2 100644
--- a/dlls/schedsvc/atsvc.c
+++ b/dlls/schedsvc/atsvc.c
@@ -99,7 +99,7 @@ static void filetime_add_ms(FILETIME *ft, LONGLONG ms)
LONGLONG ll;
} *ftll = (union u_ftll *)ft;
- ftll->ll += ms * (ULONGLONG)10000;
+ ftll->ll += ms * (LONGLONG)10000;
}
static void filetime_add_minutes(FILETIME *ft, LONG minutes)
@@ -117,7 +117,7 @@ static void filetime_add_days(FILETIME *ft, LONG days)
filetime_add_hours(ft, (LONGLONG)days * 24);
}
-static void filetime_add_weeks(FILETIME *ft, ULONG weeks)
+static void filetime_add_weeks(FILETIME *ft, LONG weeks)
{
filetime_add_days(ft, (LONGLONG)weeks * 7);
}
@@ -250,7 +250,7 @@ static BOOL trigger_get_next_runtime(const TASK_TRIGGER *trigger, const FILETIME
return FALSE;
}
-static BOOL job_get_next_runtime(struct job_t *job, FILETIME *current_ft, FILETIME *next_rt)
+static BOOL job_get_next_runtime(struct job_t *job, const FILETIME *current_ft, FILETIME *next_rt)
{
FILETIME trigger_rt;
BOOL have_next_rt = FALSE;
@@ -307,7 +307,7 @@ BOOL get_next_runtime(LARGE_INTEGER *rt)
return have_next_rt;
}
-static BOOL job_runs_at(struct job_t *job, FILETIME *begin_ft, FILETIME *end_ft)
+static BOOL job_runs_at(struct job_t *job, const FILETIME *begin_ft, const FILETIME *end_ft)
{
FILETIME job_ft;
--
2.16.3
June 27, 2018
[PATCH 2/5] mstask: Avoid an infinite loop.
by Dmitry Timoshkov
Signed-off-by: Dmitry Timoshkov <dmitry(a)baikal.ru>
---
dlls/mstask/task.c | 3 +++
1 file changed, 3 insertions(+)
diff --git a/dlls/mstask/task.c b/dlls/mstask/task.c
index 6492f16986..6c27b76c95 100644
--- a/dlls/mstask/task.c
+++ b/dlls/mstask/task.c
@@ -532,6 +532,9 @@ static HRESULT WINAPI MSTASK_ITask_GetNextRunTime(ITask *iface, SYSTEMTIME *rt)
break;
case TASK_TIME_TRIGGER_DAILY:
+ if (!This->trigger[i].Type.Daily.DaysInterval)
+ break; /* avoid infinite loop */
+
st = current_st;
st.wHour = This->trigger[i].wStartHour;
st.wMinute = This->trigger[i].wStartMinute;
--
2.16.3
June 27, 2018
[PATCH 1/5] mstask: Use current time as trigger begin time when necessary.
by Dmitry Timoshkov
Signed-off-by: Dmitry Timoshkov <dmitry(a)baikal.ru>
---
dlls/mstask/task.c | 42 +++++++++++++++++++++++-------------------
1 file changed, 23 insertions(+), 19 deletions(-)
diff --git a/dlls/mstask/task.c b/dlls/mstask/task.c
index 490229ae71..6492f16986 100644
--- a/dlls/mstask/task.c
+++ b/dlls/mstask/task.c
@@ -481,7 +481,7 @@ static HRESULT WINAPI MSTASK_ITask_GetNextRunTime(ITask *iface, SYSTEMTIME *rt)
TaskImpl *This = impl_from_ITask(iface);
HRESULT hr = SCHED_S_TASK_NO_VALID_TRIGGERS;
SYSTEMTIME st, current_st;
- FILETIME current_ft, begin_ft, end_ft, best_ft;
+ FILETIME current_ft, trigger_ft, begin_ft, end_ft, best_ft;
BOOL have_best_time = FALSE;
DWORD i;
@@ -494,12 +494,16 @@ static HRESULT WINAPI MSTASK_ITask_GetNextRunTime(ITask *iface, SYSTEMTIME *rt)
}
GetLocalTime(¤t_st);
+ SystemTimeToFileTime(¤t_st, ¤t_ft);
for (i = 0; i < This->trigger_count; i++)
{
if (!(This->trigger[i].rgFlags & TASK_TRIGGER_FLAG_DISABLED))
{
get_begin_time(&This->trigger[i], &begin_ft);
+ if (CompareFileTime(&begin_ft, ¤t_ft) < 0)
+ begin_ft = current_ft;
+
get_end_time(&This->trigger[i], &end_ft);
switch (This->trigger[i].TriggerType)
@@ -516,12 +520,12 @@ static HRESULT WINAPI MSTASK_ITask_GetNextRunTime(ITask *iface, SYSTEMTIME *rt)
st.wMinute = This->trigger[i].wStartMinute;
st.wSecond = 0;
st.wMilliseconds = 0;
- SystemTimeToFileTime(&st, ¤t_ft);
- if (CompareFileTime(&begin_ft, ¤t_ft) <= 0 && CompareFileTime(¤t_ft, &end_ft) < 0)
+ SystemTimeToFileTime(&st, &trigger_ft);
+ if (CompareFileTime(&begin_ft, &trigger_ft) <= 0 && CompareFileTime(&trigger_ft, &end_ft) < 0)
{
- if (!have_best_time || CompareFileTime(¤t_ft, &best_ft) < 0)
+ if (!have_best_time || CompareFileTime(&trigger_ft, &best_ft) < 0)
{
- best_ft = current_ft;
+ best_ft = trigger_ft;
have_best_time = TRUE;
}
}
@@ -533,20 +537,20 @@ static HRESULT WINAPI MSTASK_ITask_GetNextRunTime(ITask *iface, SYSTEMTIME *rt)
st.wMinute = This->trigger[i].wStartMinute;
st.wSecond = 0;
st.wMilliseconds = 0;
- SystemTimeToFileTime(&st, ¤t_ft);
- while (CompareFileTime(¤t_ft, &end_ft) < 0)
+ SystemTimeToFileTime(&st, &trigger_ft);
+ while (CompareFileTime(&trigger_ft, &end_ft) < 0)
{
- if (CompareFileTime(¤t_ft, &begin_ft) >= 0)
+ if (CompareFileTime(&trigger_ft, &begin_ft) >= 0)
{
- if (!have_best_time || CompareFileTime(¤t_ft, &best_ft) < 0)
+ if (!have_best_time || CompareFileTime(&trigger_ft, &best_ft) < 0)
{
- best_ft = current_ft;
+ best_ft = trigger_ft;
have_best_time = TRUE;
}
break;
}
- filetime_add_days(¤t_ft, This->trigger[i].Type.Daily.DaysInterval);
+ filetime_add_days(&trigger_ft, This->trigger[i].Type.Daily.DaysInterval);
}
break;
@@ -559,18 +563,18 @@ static HRESULT WINAPI MSTASK_ITask_GetNextRunTime(ITask *iface, SYSTEMTIME *rt)
st.wMinute = This->trigger[i].wStartMinute;
st.wSecond = 0;
st.wMilliseconds = 0;
- SystemTimeToFileTime(&st, ¤t_ft);
- while (CompareFileTime(¤t_ft, &end_ft) < 0)
+ SystemTimeToFileTime(&st, &trigger_ft);
+ while (CompareFileTime(&trigger_ft, &end_ft) < 0)
{
- FileTimeToSystemTime(¤t_ft, &st);
+ FileTimeToSystemTime(&trigger_ft, &st);
- if (CompareFileTime(¤t_ft, &begin_ft) >= 0)
+ if (CompareFileTime(&trigger_ft, &begin_ft) >= 0)
{
if (This->trigger[i].Type.Weekly.rgfDaysOfTheWeek & (1 << st.wDayOfWeek))
{
- if (!have_best_time || CompareFileTime(¤t_ft, &best_ft) < 0)
+ if (!have_best_time || CompareFileTime(&trigger_ft, &best_ft) < 0)
{
- best_ft = current_ft;
+ best_ft = trigger_ft;
have_best_time = TRUE;
}
break;
@@ -578,9 +582,9 @@ static HRESULT WINAPI MSTASK_ITask_GetNextRunTime(ITask *iface, SYSTEMTIME *rt)
}
if (st.wDayOfWeek == 0 && This->trigger[i].Type.Weekly.WeeksInterval > 1) /* Sunday, goto next week */
- filetime_add_weeks(¤t_ft, This->trigger[i].Type.Weekly.WeeksInterval - 1);
+ filetime_add_weeks(&trigger_ft, This->trigger[i].Type.Weekly.WeeksInterval - 1);
else /* check next weekday */
- filetime_add_days(¤t_ft, 1);
+ filetime_add_days(&trigger_ft, 1);
}
break;
--
2.16.3
June 27, 2018
[PATCH] testbot/web: Let GetHtmlLine() detect and format the timeout errors.
by Francois Gouget
It already handles filtering and highlighting errors so it makes sense
to also have if reformat the timeout errors for the log summary.
Signed-off-by: Francois Gouget <fgouget(a)codeweavers.com>
---
testbot/web/JobDetails.pl | 15 ++++++---------
1 file changed, 6 insertions(+), 9 deletions(-)
diff --git a/testbot/web/JobDetails.pl b/testbot/web/JobDetails.pl
index e5f792929..e7e53d208 100644
--- a/testbot/web/JobDetails.pl
+++ b/testbot/web/JobDetails.pl
@@ -253,6 +253,11 @@ sub GetHtmlLine($$$)
return undef if ($Category ne "error" and !$FullLog);
my $Html = $self->escapeHTML($Line);
+ if (!$FullLog and $Html =~ m/^[^:]+:([^:]*)(?::[0-9a-f]+)? done \(258\)/)
+ {
+ my $Unit = $1;
+ return $Unit ne "" ? "$Unit: Timeout" : "Timeout";
+ }
if ($FullLog and $Category ne "none")
{
# Highlight all line categories in the full log
@@ -414,15 +419,7 @@ sub GenerateBody($)
print "<pre><code>";
$LogFirst = 0;
}
- if (!$MoreInfo->{Full} && $Line =~ m/^[^:]+:([^:]*)(?::[0-9a-f]+)? done \(258\)/)
- {
- my $Unit = $1 ne "" ? "$1: " : "";
- print "${Unit}Timeout\n";
- }
- else
- {
- print "$Html\n";
- }
+ print "$Html\n";
}
close($LogFile);
--
2.18.0
June 27, 2018
[PATCH] testbot: Track patches to the Wine modules separately.
by Francois Gouget
Patches to the dlls and programs modules don't require a rebuild of
the native Wine tools.
Signed-off-by: Francois Gouget <fgouget(a)codeweavers.com>
---
testbot/lib/WineTestBot/PatchUtils.pm | 13 +++++++++++++
testbot/lib/WineTestBot/Patches.pm | 3 ++-
2 files changed, 15 insertions(+), 1 deletion(-)
diff --git a/testbot/lib/WineTestBot/PatchUtils.pm b/testbot/lib/WineTestBot/PatchUtils.pm
index b2bfe6a9a..811c3b8b2 100644
--- a/testbot/lib/WineTestBot/PatchUtils.pm
+++ b/testbot/lib/WineTestBot/PatchUtils.pm
@@ -193,6 +193,19 @@ sub _HandleFile($$$)
}
$Tests->{$Module}->{Files}->{$File} = $Change;
}
+ elsif ($FilePath =~ m~^(dlls|programs)/([^/]+)/([^/\s]+)$~)
+ {
+ my ($Root, $Dir, $File) = ($1, $2, $3);
+ my $Module = ($Root eq "programs") ? "$Dir.exe" : $Dir;
+ $Impacts->{IsWinePatch} = 1;
+ $Impacts->{ModuleBuild} = 1;
+
+ if ($File eq "Makefile.in" and $Change ne "modify")
+ {
+ # This adds / removes a directory
+ $Impacts->{MakeMakefiles} = 1;
+ }
+ }
else
{
my $WineFiles = $Impacts->{WineFiles} || $_WineFiles;
diff --git a/testbot/lib/WineTestBot/Patches.pm b/testbot/lib/WineTestBot/Patches.pm
index fe333d943..50f720861 100644
--- a/testbot/lib/WineTestBot/Patches.pm
+++ b/testbot/lib/WineTestBot/Patches.pm
@@ -136,7 +136,8 @@ sub Submit($$$)
$PastImpacts = GetPatchImpact($PatchFileName) if ($IsSet);
my $Impacts = GetPatchImpact("$DataDir/patches/" . $self->Id, undef, $PastImpacts);
- if (!$Impacts->{WineBuild} and !$Impacts->{TestBuild})
+ if (!$Impacts->{WineBuild} and !$Impacts->{ModuleBuild} and
+ !$Impacts->{TestBuild})
{
if ($Impacts->{IsWinePatch})
{
--
2.18.0
June 27, 2018
[PATCH] testbot/WineRun*: Prefix the TestBot errors so they are easy to identify.
by Francois Gouget
Some scripts may need to detect them.
Signed-off-by: Francois Gouget <fgouget(a)codeweavers.com>
---
testbot/bin/WineRunBuild.pl | 2 +-
testbot/bin/WineRunReconfig.pl | 2 +-
testbot/bin/WineRunTask.pl | 2 +-
testbot/bin/WineRunWineTest.pl | 2 +-
4 files changed, 4 insertions(+), 4 deletions(-)
diff --git a/testbot/bin/WineRunBuild.pl b/testbot/bin/WineRunBuild.pl
index 176ade6b6..90b9f030a 100755
--- a/testbot/bin/WineRunBuild.pl
+++ b/testbot/bin/WineRunBuild.pl
@@ -269,7 +269,7 @@ sub FatalError($;$)
my ($ErrMessage, $Retry) = @_;
LogMsg "$JobId/$StepNo/$TaskNo $ErrMessage";
- LogTaskError($ErrMessage);
+ LogTaskError("BotError: $ErrMessage");
WrapUpAndExit('boterror', $Retry);
}
diff --git a/testbot/bin/WineRunReconfig.pl b/testbot/bin/WineRunReconfig.pl
index aa0cf955e..8a3d955a7 100755
--- a/testbot/bin/WineRunReconfig.pl
+++ b/testbot/bin/WineRunReconfig.pl
@@ -269,7 +269,7 @@ sub FatalError($;$)
my ($ErrMessage, $Retry) = @_;
LogMsg "$JobId/$StepNo/$TaskNo $ErrMessage";
- LogTaskError($ErrMessage);
+ LogTaskError("BotError: $ErrMessage");
WrapUpAndExit('boterror', $Retry);
}
diff --git a/testbot/bin/WineRunTask.pl b/testbot/bin/WineRunTask.pl
index 821ca55ea..fb2966303 100755
--- a/testbot/bin/WineRunTask.pl
+++ b/testbot/bin/WineRunTask.pl
@@ -319,7 +319,7 @@ sub FatalError($;$)
my ($ErrMessage, $Retry) = @_;
LogMsg "$JobId/$StepNo/$TaskNo $ErrMessage";
- LogTaskError($ErrMessage);
+ LogTaskError("BotError: $ErrMessage");
WrapUpAndExit('boterror', undef, $Retry);
}
diff --git a/testbot/bin/WineRunWineTest.pl b/testbot/bin/WineRunWineTest.pl
index 83cf5821b..1e43f9a41 100755
--- a/testbot/bin/WineRunWineTest.pl
+++ b/testbot/bin/WineRunWineTest.pl
@@ -320,7 +320,7 @@ sub FatalError($;$)
my ($ErrMessage, $Retry) = @_;
LogMsg "$JobId/$StepNo/$TaskNo $ErrMessage";
- LogTaskError($ErrMessage);
+ LogTaskError("BotError: $ErrMessage");
WrapUpAndExit('boterror', undef, $Retry);
}
--
2.18.0
June 27, 2018
[PATCH] testbot/CheckForWinetestUpdate: Fix the Wine reconfig timeout.
by Francois Gouget
Signed-off-by: Francois Gouget <fgouget(a)codeweavers.com>
---
testbot/bin/CheckForWinetestUpdate.pl | 4 +++-
1 file changed, 3 insertions(+), 1 deletion(-)
diff --git a/testbot/bin/CheckForWinetestUpdate.pl b/testbot/bin/CheckForWinetestUpdate.pl
index d3ef384c7..a570a1b80 100755
--- a/testbot/bin/CheckForWinetestUpdate.pl
+++ b/testbot/bin/CheckForWinetestUpdate.pl
@@ -286,7 +286,9 @@ sub AddReconfigJob($)
Debug(" $VMKey $VMType reconfig\n");
my $Task = $BuildStep->Tasks->Add();
$Task->VM($VM);
- $Task->Timeout($ReconfigTimeout);
+ $Task->Timeout($VMType eq "wine" ?
+ 3 * $WineReconfigTimeout : # 3 full Wine builds
+ $ReconfigTimeout); # 1 overall timeout
}
# Save the build step so the others can reference it.
--
2.18.0
June 27, 2018
[PATCH] testbot/web: Compile patches on wow64 if 64 bit tests have been selected.
by Francois Gouget
Signed-off-by: Francois Gouget <fgouget(a)codeweavers.com>
---
testbot/web/Submit.pl | 45 ++++++++++++++++++++++++-------------------
1 file changed, 25 insertions(+), 20 deletions(-)
diff --git a/testbot/web/Submit.pl b/testbot/web/Submit.pl
index 9fa252a11..38aa75fcb 100644
--- a/testbot/web/Submit.pl
+++ b/testbot/web/Submit.pl
@@ -858,30 +858,35 @@ sub OnSubmit($)
my $VMs = CreateVMs();
$VMs->AddFilter("Type", ["wine"]);
my $SortedKeys = $VMs->SortKeysBySortOrder($VMs->GetKeys());
- foreach my $VMKey (@$SortedKeys)
+ foreach my $Build ("win32", "wow64")
{
- my $VM = $VMs->GetItem($VMKey);
- my $FieldName = "vm_" . $self->CGI->escapeHTML($VMKey);
- next if (!$self->GetParam($FieldName)); # skip unselected VMs
+ next if ($Build eq "wow64" and !defined($self->GetParam("Run64")));
- if (!$Tasks)
+ foreach my $VMKey (@$SortedKeys)
{
- # First create the Wine test step
- my $WineStep = $Steps->Add();
- $WineStep->FileName($BaseName);
- $WineStep->FileType($FileType);
- $WineStep->InStaging(!1);
- $WineStep->Type("build");
- $WineStep->DebugLevel($self->GetParam("DebugLevel"));
- $WineStep->ReportSuccessfulTests(defined($self->GetParam("ReportSuccessfulTests")));
- $Tasks = $WineStep->Tasks;
- }
+ my $VM = $VMs->GetItem($VMKey);
+ my $FieldName = "vm_" . $self->CGI->escapeHTML($VMKey);
+ next if (!$self->GetParam($FieldName)); # skip unselected VMs
- # Then add a task for this VM
- my $Task = $Tasks->Add();
- $Task->VM($VM);
- $Task->CmdLineArg("win32");
- $Task->Timeout($WineReconfigTimeout);
+ if (!$Tasks)
+ {
+ # First create the Wine test step
+ my $WineStep = $Steps->Add();
+ $WineStep->FileName($BaseName);
+ $WineStep->FileType($FileType);
+ $WineStep->InStaging(!1);
+ $WineStep->Type("build");
+ $WineStep->DebugLevel($self->GetParam("DebugLevel"));
+ $WineStep->ReportSuccessfulTests(defined($self->GetParam("ReportSuccessfulTests")));
+ $Tasks = $WineStep->Tasks;
+ }
+
+ # Then add a task for this VM
+ my $Task = $Tasks->Add();
+ $Task->VM($VM);
+ $Task->CmdLineArg($Build);
+ $Task->Timeout($WineReconfigTimeout);
+ }
}
}
--
2.18.0
June 27, 2018
[PATCH] testbot: Fix the detection of the start and skipped report lines.
by Francois Gouget
This now matches the Wine report parser.
Signed-off-by: Francois Gouget <fgouget(a)codeweavers.com>
---
testbot/lib/WineTestBot/LogUtils.pm | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/testbot/lib/WineTestBot/LogUtils.pm b/testbot/lib/WineTestBot/LogUtils.pm
index 2d3042ec7..bccf30db3 100644
--- a/testbot/lib/WineTestBot/LogUtils.pm
+++ b/testbot/lib/WineTestBot/LogUtils.pm
@@ -408,7 +408,7 @@ sub GetLogLineCategory($)
return "todo";
}
if ($Line =~ /: Tests skipped: / or
- $Line =~ /^\w+:\w+ skipped /)
+ $Line =~ /^[_.a-z0-9-]+:[_a-z0-9]* skipped /)
{
return "skip";
}
@@ -431,7 +431,7 @@ sub GetLogLineCategory($)
return "error";
}
if ($Line =~ /^\+ \S/ or
- $Line =~ /^\w+:\w+ start / or
+ $Line =~ /^[_.a-z0-9-]+:[_a-z0-9]* start / or
# Build messages
$Line =~ /^(?:Build|Reconfig|Task): ok/)
{
--
2.18.0
June 27, 2018
[PATCH 3/3] testbot: Run WineTest on Wine VMs after commits.
by Francois Gouget
WineReconfig.pl now knows how to retrieve and cache the Gecko and Mono
addons, and how to create new wineprefixes. These are then captured by
the updated snapshot and are thus ready to use to run tests.
CheckForWinetestUpdate.pl creates additional steps to rerun the full
WineTest suite on the Wine VMs if the Wine rebuild was successful.
Running WineTest is handled by WineTest.pl and WineRunWineTest.pl
collects the corresponding reports in the latest directory in files
named '<vm>_<build>.report' where build is one of win32, wow32 or
wow64.
Signed-off-by: Francois Gouget <fgouget(a)codeweavers.com>
---
testbot/bin/CheckForWinetestUpdate.pl | 44 +++++-
testbot/bin/WineRunWineTest.pl | 218 ++++++++++++++++++++++----
testbot/bin/build/WineReconfig.pl | 189 ++++++++++++++++++++--
testbot/bin/build/WineTest.pl | 118 ++++++++++++--
testbot/lib/WineTestBot/LogUtils.pm | 8 +-
testbot/lib/WineTestBot/Utils.pm | 19 ++-
6 files changed, 537 insertions(+), 59 deletions(-)
diff --git a/testbot/bin/CheckForWinetestUpdate.pl b/testbot/bin/CheckForWinetestUpdate.pl
index 74c59955f..d3ef384c7 100755
--- a/testbot/bin/CheckForWinetestUpdate.pl
+++ b/testbot/bin/CheckForWinetestUpdate.pl
@@ -273,10 +273,10 @@ sub AddReconfigJob($)
# Add a step to the job
my $Steps = $NewJob->Steps;
- my $NewStep = $Steps->Add();
- $NewStep->Type("reconfig");
- $NewStep->FileType("none");
- $NewStep->InStaging(!1);
+ my $BuildStep = $Steps->Add();
+ $BuildStep->Type("reconfig");
+ $BuildStep->FileType("none");
+ $BuildStep->InStaging(!1);
# And a task for each VM
my $SortedKeys = $VMs->SortKeysBySortOrder($VMs->GetKeys());
@@ -284,14 +284,46 @@ sub AddReconfigJob($)
{
my $VM = $VMs->GetItem($VMKey);
Debug(" $VMKey $VMType reconfig\n");
- my $Task = $NewStep->Tasks->Add();
+ my $Task = $BuildStep->Tasks->Add();
$Task->VM($VM);
$Task->Timeout($ReconfigTimeout);
}
- # Save it all
+ # Save the build step so the others can reference it.
my ($ErrKey, $ErrProperty, $ErrMessage) = $Jobs->Save();
if (defined $ErrMessage)
+ {
+ Error "Failed to save the build step: $ErrMessage\n";
+ return 0;
+ }
+
+ if ($VMType eq "wine")
+ {
+ # Add steps to run WineTest on Wine
+ foreach my $Build ("win32", "wow32", "wow64")
+ {
+ # Add a step to the job
+ my $NewStep = $Steps->Add();
+ $NewStep->PreviousNo($BuildStep->No);
+ $NewStep->Type("suite");
+ $NewStep->FileType("none");
+ $NewStep->InStaging(!1);
+
+ foreach my $VMKey (@$SortedKeys)
+ {
+ my $VM = $VMs->GetItem($VMKey);
+ Debug(" $VMKey $Build\n");
+ my $Task = $NewStep->Tasks->Add();
+ $Task->VM($VM);
+ $Task->CmdLineArg($Build);
+ $Task->Timeout($SuiteTimeout);
+ }
+ }
+ }
+
+ # Save it all
+ ($ErrKey, $ErrProperty, $ErrMessage) = $Jobs->Save();
+ if (defined $ErrMessage)
{
Error "Failed to save the Reconfig job: $ErrMessage\n";
return 0;
diff --git a/testbot/bin/WineRunWineTest.pl b/testbot/bin/WineRunWineTest.pl
index 53a2a0929..83cf5821b 100755
--- a/testbot/bin/WineRunWineTest.pl
+++ b/testbot/bin/WineRunWineTest.pl
@@ -1,7 +1,7 @@
#!/usr/bin/perl -Tw
# -*- Mode: Perl; perl-indent-level: 2; indent-tabs-mode: nil -*-
#
-# Makes sure the Wine patches compile.
+# Makes sure the Wine patches compile or run WineTest.
# See the bin/build/WineTest.pl script.
#
# Copyright 2018 Francois Gouget
@@ -46,6 +46,7 @@ use WineTestBot::PatchUtils;
use WineTestBot::VMs;
use WineTestBot::Log;
use WineTestBot::LogUtils;
+use WineTestBot::Utils;
use WineTestBot::Engine::Notify;
@@ -67,6 +68,35 @@ sub Error(@)
}
+#
+# Task helpers
+#
+
+sub TakeScreenshot($$)
+{
+ my ($VM, $FileName) = @_;
+
+ my $Domain = $VM->GetDomain();
+ my ($ErrMessage, $ImageSize, $ImageBytes) = $Domain->CaptureScreenImage();
+ if (!defined $ErrMessage)
+ {
+ if (open(my $Screenshot, ">", $FileName))
+ {
+ print $Screenshot $ImageBytes;
+ close($Screenshot);
+ }
+ else
+ {
+ Error "Could not open the screenshot file for writing: $!\n";
+ }
+ }
+ elsif ($Domain->IsPoweredOn())
+ {
+ Error "Could not capture a screenshot: $ErrMessage\n";
+ }
+}
+
+
#
# Setup and command line processing
#
@@ -190,15 +220,17 @@ sub LogTaskError($)
}
}
-sub WrapUpAndExit($;$$)
+sub WrapUpAndExit($;$$$)
{
- my ($Status, $Retry, $Timeout) = @_;
+ my ($Status, $TestFailures, $Retry, $TimedOut) = @_;
my $NewVMStatus = $Status eq 'queued' ? 'offline' : 'dirty';
my $VMResult = $Status eq "boterror" ? "boterror" :
$Status eq "queued" ? "error" :
- $Timeout ? "timeout" : "";
+ $TimedOut ? "timeout" : "";
+
+ Debug(Elapsed($Start), " Taking a screenshot\n");
+ TakeScreenshot($VM, "$TaskDir/screenshot.png");
- my $TestFailures;
my $Tries = $Task->TestFailures || 0;
if ($Retry)
{
@@ -253,6 +285,30 @@ sub WrapUpAndExit($;$$)
$VM->Save();
}
+ if ($Step->Type eq 'suite' and $Status eq 'completed' and !$TimedOut)
+ {
+ my $BuildList = $Task->CmdLineArg;
+ $BuildList =~ s/ .*$//;
+ foreach my $Build (split /,/, $BuildList)
+ {
+ # Keep the old report if the new one is missing
+ my $RptFileName = "$Build.report";
+ if (-f "$TaskDir/$RptFileName" and !-z "$TaskDir/$RptFileName")
+ {
+ # Update the reference VM suite results for WineSendLog.pl
+ my $LatestBaseName = join("", "$DataDir/latest/", $Task->VM->Name,
+ "_$Build");
+ unlink("$LatestBaseName.log");
+ link("$TaskDir/$RptFileName", "$LatestBaseName.log");
+ unlink("$LatestBaseName.err");
+ if (-f "$TaskDir/err" and !-z "$TaskDir/err")
+ {
+ link("$TaskDir/err", "$LatestBaseName.err");
+ }
+ }
+ }
+ }
+
my $Result = $VM->Name .": ". $VM->Status ." Status: $Status Failures: ". (defined $TestFailures ? $TestFailures : "unset");
LogMsg "Task $JobId/$StepNo/$TaskNo done ($Result)\n";
Debug(Elapsed($Start), " Done. $Result\n");
@@ -266,12 +322,12 @@ sub FatalError($;$)
LogMsg "$JobId/$StepNo/$TaskNo $ErrMessage";
LogTaskError($ErrMessage);
- WrapUpAndExit('boterror', $Retry);
+ WrapUpAndExit('boterror', undef, $Retry);
}
-sub FatalTAError($$)
+sub FatalTAError($$;$)
{
- my ($TA, $ErrMessage) = @_;
+ my ($TA, $ErrMessage, $PossibleCrash) = @_;
$ErrMessage .= ": ". $TA->GetLastError() if (defined $TA);
# A TestAgent operation failed, see if the VM is still accessible
@@ -297,7 +353,13 @@ sub FatalTAError($$)
else
{
# Ignore the TestAgent error, it's irrelevant
- $ErrMessage = "The test VM is powered off!\n";
+ $ErrMessage = "The test VM is powered off! Did the test shut it down?\n";
+ }
+ if ($PossibleCrash and !$Task->CanRetry())
+ {
+ # The test did it!
+ LogTaskError($ErrMessage);
+ WrapUpAndExit('completed', 1);
}
FatalError($ErrMessage, $Retry);
}
@@ -320,33 +382,78 @@ elsif (!$VM->GetDomain()->IsPoweredOn())
FatalError("The VM is not powered on\n");
}
-if ($Step->FileType ne "patchdlls")
+if (($Step->Type eq "suite" and $Step->FileType ne "none") or
+ ($Step->Type ne "suite" and $Step->FileType ne "patchdlls"))
{
FatalError("Unexpected file type '". $Step->FileType ."' found\n");
}
#
-# Run the task
+# Setup the VM
#
+my $TA = $VM->GetAgent();
+Debug(Elapsed($Start), " Setting the time\n");
+if (!$TA->SetTime())
+{
+ # Not a fatal error. Try the next port in case the VM runs a privileged
+ # TestAgentd daemon there.
+ my $PrivilegedTA = $VM->GetAgent(1);
+ if (!$PrivilegedTA->SetTime())
+ {
+ LogTaskError("Unable to set the VM system time: ". $PrivilegedTA->GetLastError() .". Maybe the TestAgentd process is missing the required privileges.\n");
+ $PrivilegedTA->Disconnect();
+ }
+}
my $FileName = $Step->GetFullFileName();
-my $TA = $VM->GetAgent();
-Debug(Elapsed($Start), " Sending '$FileName'\n");
-if (!$TA->SendFile($FileName, "staging/patch.diff", 0))
+if (defined $FileName)
{
- FatalTAError($TA, "Could not copy the patch to the VM");
+ Debug(Elapsed($Start), " Sending '$FileName'\n");
+ if (!$TA->SendFile($FileName, "staging/patch.diff", 0))
+ {
+ FatalTAError($TA, "Could not copy the patch to the VM");
+ }
}
+
my $Script = "#!/bin/sh\n".
- "( set -x\n" .
- " ../bin/build/WineTest.pl ". $Task->CmdLineArg ." build patch.diff\n".
- ") >Task.log 2>&1\n";
+ "( set -x\n".
+ " ../bin/build/WineTest.pl ";
+if ($Step->Type eq "suite")
+{
+ my $Tag = lc($VM->Name);
+ $Tag =~ s/^$TagPrefix//;
+ $Tag =~ s/[^a-zA-Z0-9]/-/g;
+ $Script .= $Task->CmdLineArg .",submit winetest $TagPrefix-$Tag ";
+ if (defined $WebHostName)
+ {
+ my $StepTask = 100 * $StepNo + $TaskNo;
+ $Script .= "-u \"http://$WebHostName/JobDetails.pl?Key=$JobId&s$StepTask=1#k$StepTask\" ";
+ }
+ my $Info = $VM->Description ? $VM->Description : "";
+ if ($VM->Details)
+ {
+ $Info .= ": " if ($Info ne "");
+ $Info .= $VM->Details;
+ }
+ $Script .= join(" ", "-m", ShQuote($AdminEMail), "-i", ShQuote($Info));
+}
+else
+{
+ $Script .= $Task->CmdLineArg ." build patch.diff";
+}
+$Script .= "\n) >Task.log 2>&1\n";
Debug(Elapsed($Start), " Sending the script: [$Script]\n");
if (!$TA->SendFileFromString($Script, "task", $TestAgent::SENDFILE_EXE))
{
FatalTAError($TA, "Could not send the task script to the VM");
}
+
+#
+# Run the test
+#
+
Debug(Elapsed($Start), " Starting the script\n");
my $Pid = $TA->Run(["./task"], 0);
if (!$Pid)
@@ -357,10 +464,11 @@ if (!$Pid)
#
# From that point on we want to at least try to grab the task log
-# before giving up
+# and a screenshot before giving up
#
-my ($NewStatus, $ErrMessage, $TAError, $TaskTimedOut);
+my $NewStatus = 'completed';
+my ($TaskFailures, $TaskTimedOut, $ErrMessage, $TAError, $PossibleCrash);
Debug(Elapsed($Start), " Waiting for the script (", $Task->Timeout, "s timeout)\n");
if (!defined $TA->Wait($Pid, $Task->Timeout, 60))
{
@@ -368,11 +476,19 @@ if (!defined $TA->Wait($Pid, $Task->Timeout, 60))
if ($ErrMessage =~ /timed out waiting for the child process/)
{
$ErrMessage = "The task timed out\n";
- $NewStatus = "badbuild";
+ if ($Step->Type eq "build")
+ {
+ $NewStatus = "badbuild";
+ }
+ else
+ {
+ $TaskFailures = 1;
+ }
$TaskTimedOut = 1;
}
else
{
+ $PossibleCrash = 1 if ($Step->Type ne "build");
$TAError = "An error occurred while waiting for the task to complete: $ErrMessage";
$ErrMessage = undef;
}
@@ -399,10 +515,11 @@ if ($TA->GetFile("Task.log", "$TaskDir/log"))
{
FatalError("$Result\n", "retry");
}
- else
+ elsif ($Result ne "missing" or $Step->Type ne "suite")
{
- # If the result line is missing we probably already have an error message
- # that explains why.
+ # There is no build and thus no result line when running WineTest.
+ # Otherwise if the result line is missing we probably already have an
+ # error message that explains why.
$NewStatus = "badbuild";
}
}
@@ -411,15 +528,62 @@ elsif (!defined $TAError)
$TAError = "An error occurred while retrieving the task log: ". $TA->GetLastError();
}
+#
+# Grab the test logs if any
+#
+
+my $TimedOut;
+if ($Step->Type ne "build")
+{
+ my $TaskDir = $Task->CreateDir();
+ my $BuildList = $Task->CmdLineArg;
+ $BuildList =~ s/ .*$//;
+ foreach my $Build (split /,/, $BuildList)
+ {
+ my $RptFileName = "$Build.report";
+ Debug(Elapsed($Start), " Retrieving '$RptFileName'\n");
+ if ($TA->GetFile($RptFileName, "$TaskDir/$RptFileName"))
+ {
+ chmod 0664, "$TaskDir/$RptFileName";
+
+ (my $LogFailures, my $LogErrors, $TimedOut) = ParseWineTestReport("$TaskDir/$RptFileName", 1, $Step->Type eq "suite", $TaskTimedOut);
+ if (!defined $LogFailures and @$LogErrors == 1)
+ {
+ # Could not open the file
+ $NewStatus = 'boterror';
+ Error "Unable to open '$RptFileName' for reading: $!\n";
+ LogTaskError("Unable to open '$RptFileName' for reading: $!\n");
+ }
+ else
+ {
+ # $LogFailures can legitimately be undefined in case of a timeout
+ $TaskFailures += $LogFailures || 0;
+ foreach my $Error (@$LogErrors)
+ {
+ LogTaskError("$Error\n");
+ }
+ }
+ }
+ elsif (!defined $TAError and
+ $TA->GetLastError() !~ /: No such file or directory/)
+ {
+ $TAError = "An error occurred while retrieving $RptFileName: ". $TA->GetLastError();
+ $NewStatus = 'boterror';
+ }
+ }
+}
+
+Debug(Elapsed($Start), " Disconnecting\n");
+$TA->Disconnect();
+
# Report the task errors even though they may have been caused by
# TestAgent trouble.
LogTaskError($ErrMessage) if (defined $ErrMessage);
-FatalTAError(undef, $TAError) if (defined $TAError);
-$TA->Disconnect();
+FatalTAError(undef, $TAError, $PossibleCrash) if (defined $TAError);
#
# Wrap up
#
-WrapUpAndExit($NewStatus, undef, $TaskTimedOut);
+WrapUpAndExit($NewStatus, $TaskFailures, undef, $TaskTimedOut || $TimedOut);
diff --git a/testbot/bin/build/WineReconfig.pl b/testbot/bin/build/WineReconfig.pl
index b030051c6..e3f14e243 100755
--- a/testbot/bin/build/WineReconfig.pl
+++ b/testbot/bin/build/WineReconfig.pl
@@ -40,6 +40,9 @@ my $Name0 = $0;
$Name0 =~ s+^.*/++;
+use Digest::SHA;
+use File::Path;
+
use WineTestBot::Config;
use WineTestBot::PatchUtils;
@@ -126,7 +129,7 @@ sub BuildWine($$$$)
{
my ($Targets, $NoRm, $Build, $Extras) = @_;
- return 1 if (!$Targets->{$Build});
+ return 1 if (!$Targets->{build} or !$Targets->{$Build});
mkdir "$DataDir/build-$Build" if (!-d "$DataDir/build-$Build");
# If $NoRm is not set, rebuild from scratch to make sure cruft will not
@@ -134,7 +137,7 @@ sub BuildWine($$$$)
InfoMsg "\nRebuilding the $Build Wine\n";
system("cd '$DataDir/build-$Build' && set -x && ".
($NoRm ? "" : "rm -rf * && ") .
- "time ../wine/configure $Extras --disable-winetest && ".
+ "time ../wine/configure $Extras && ".
"time make -j$ncpus");
if ($? != 0)
{
@@ -146,6 +149,154 @@ sub BuildWine($$$$)
}
+#
+# WinePrefix helpers
+#
+
+sub VerifyAddOn($$)
+{
+ my ($AddOn, $Arch) = @_;
+
+ my $Sha256 = Digest::SHA->new(256);
+ eval { $Sha256->addfile("$DataDir/$AddOn->{name}/$AddOn->{filename}") };
+ return "$@" if ($@);
+
+ my $Checksum = $Sha256->hexdigest();
+ return undef if ($Checksum eq $AddOn->{$Arch});
+ return "Bad checksum for '$AddOn->{filename}'";
+}
+
+sub UpdateAddOn($$$)
+{
+ my ($AddOn, $Name, $Arch) = @_;
+
+ if (!defined $AddOn)
+ {
+ LogMsg "Could not get information on the $Name addon\n";
+ return 0;
+ }
+ if (!$AddOn->{version})
+ {
+ LogMsg "Could not get the $Name version\n";
+ return 0;
+ }
+ if (!$AddOn->{$Arch})
+ {
+ LogMsg "Could not get the $Name $Arch checksum\n";
+ return 0;
+ }
+
+ $AddOn->{filename} = "wine". ($Name eq "gecko" ? "_" : "-") .
+ "$Name-$AddOn->{version}".
+ ($Arch eq "" ? "" : "-$Arch") .".msi";
+ return 1 if (!VerifyAddOn($AddOn, $Arch));
+
+ InfoMsg "Downloading $AddOn->{filename}\n";
+ mkdir "$DataDir/$Name";
+
+ my $Url="http://dl.winehq.org/wine/wine-$Name/$AddOn->{version}/$AddOn->{filename}";
+ for (1..3)
+ {
+ system("cd '$DataDir/$Name' && set -x && ".
+ "wget --no-verbose -O- '$Url' >'$AddOn->{filename}'");
+ last if ($? == 0);
+ }
+ my $ErrMessage = VerifyAddOn($AddOn, $Arch);
+ return 1 if (!defined $ErrMessage);
+ LogMsg "$ErrMessage\n";
+ return 0;
+}
+
+sub UpdateAddOns($)
+{
+ my ($Targets) = @_;
+ return 1 if (!$Targets->{addons});
+
+ my %AddOns;
+ if (open(my $fh, "<", "$DataDir/wine/dlls/appwiz.cpl/addons.c"))
+ {
+ my $Arch = "";
+ while (my $Line= <$fh>)
+ {
+ if ($Line =~ /^\s*#\s*define\s+ARCH_STRING\s+"([^"]+)"/)
+ {
+ $Arch = $1;
+ }
+ elsif ($Line =~ /^\s*#\s*define\s*(GECKO|MONO)_VERSION\s*"([^"]+)"/)
+ {
+ my ($AddOn, $Version) = ($1, $2);
+ $AddOn =~ tr/A-Z/a-z/;
+ $AddOns{$AddOn}->{name} = $AddOn;
+ $AddOns{$AddOn}->{version} = $Version;
+ }
+ elsif ($Line =~ /^\s*#\s*define\s*(GECKO|MONO)_SHA\s*"([^"]+)"/)
+ {
+ my ($AddOn, $Checksum) = ($1, $2);
+ $AddOn =~ tr/A-Z/a-z/;
+ $AddOns{$AddOn}->{$Arch} = $Checksum;
+ $Arch = "";
+ }
+ }
+ close($fh);
+ }
+ else
+ {
+ LogMsg "Could not open 'wine/dlls/appwiz.cpl/addons.c': $!\n";
+ return 0;
+ }
+
+ return UpdateAddOn($AddOns{gecko}, "gecko", "x86") &&
+ UpdateAddOn($AddOns{gecko}, "gecko", "x86_64") &&
+ UpdateAddOn($AddOns{mono}, "mono", "");
+}
+
+# See also WineTest.pl
+sub SetupWineEnvironment($)
+{
+ my ($Build) = @_;
+
+ $ENV{WINEPREFIX} = "$DataDir/wineprefix-$Build";
+ $ENV{DISPLAY} ||= ":0.0";
+}
+
+# See also WineTest.pl
+sub RunWine($$$)
+{
+ my ($Build, $Cmd, $CmdArgs) = @_;
+
+ my $Magic = `cd '$DataDir/build-$Build' && file $Cmd`;
+ my $Wine = ($Magic =~ /ELF 64/ ? "./wine64" : "./wine");
+ return system("cd '$DataDir/build-$Build' && set -x && ".
+ "time $Wine $Cmd $CmdArgs");
+}
+
+# Setup a brand new WinePrefix ready for use for testing.
+# This way we do it once instead of doing it for every test, thus saving
+# time. Note that this requires using a different wineprefix for each build.
+sub NewWinePrefix($$)
+{
+ my ($Targets, $Build) = @_;
+
+ return 1 if (!$Targets->{wineprefix} or !$Targets->{$Build});
+
+ InfoMsg "\nRecreating the $Build wineprefix\n";
+ SetupWineEnvironment($Build);
+ rmtree($ENV{WINEPREFIX});
+
+ # Crash dialogs cause delays so disable them
+ if (RunWine($Build, "./programs/reg/reg.exe.so", "ADD HKCU\\\\Software\\\\Wine\\\\WineDbg /v ShowCrashDialog /t REG_DWORD /d 0"))
+ {
+ LogMsg "Failed to disable the $Build build crash dialogs: $!\n";
+ return 0;
+ }
+
+ # Ensure the WinePrefix has been fully created before updating the snapshot
+ system("cd '$DataDir/build-$Build' && ./server/wineserver -w");
+
+ return 1;
+}
+
+
#
# Setup and command line processing
#
@@ -154,7 +305,7 @@ $ENV{PATH} = "/usr/lib/ccache:/usr/bin:/bin";
delete $ENV{ENV};
my %AllTargets;
-map { $AllTargets{$_} = 1 } qw(update win32 wow32 wow64);
+map { $AllTargets{$_} = 1 } qw(update addons build wineprefix win32 wow32 wow64);
my ($Usage, $TargetList, $NoRm);
while (@ARGV)
@@ -212,15 +363,18 @@ if (defined $Usage)
}
print "Usage: $Name0 [--no-rm] [--help] [TARGETS]\n";
print "\n";
- print "Performs all the tasks needed for the host to be ready to test new patches: update the Wine source and rebuild the Wine binaries.\n";
+ print "Performs all the tasks needed for the host to be ready to test new patches: update the Wine source and addons, and rebuild the Wine binaries.\n";
print "\n";
print "Where:\n";
print " TARGETS Is a comma-separated list of targets to process. By default all\n";
print " targets are processed.\n";
print " - update: Update Wine's source code.\n";
- print " - win32: Rebuild the regular 32 bit Wine.\n";
- print " - wow32: Rebuild the 32 bit WoW Wine.\n";
- print " - wow64: Rebuild the 64 bit WoW Wine.\n";
+ print " - build: Update the Wine builds.\n";
+ print " - addons: Update the Gecko and Mono Wine addons.\n";
+ print " - wineprefix: Update the wineprefixes.\n";
+ print " - win32: Apply the above to the regular 32 bit Wine.\n";
+ print " - wow32: Apply the above to the 32 bit WoW Wine.\n";
+ print " - wow64: Apply the above to the 64 bit WoW Wine.\n";
print " --no-rm Don't rebuild from scratch.\n";
print " --help Shows this usage message.\n";
exit 0;
@@ -240,16 +394,25 @@ if ($DataDir =~ /'/)
#
-# Run the builds
+# Run the builds and/or tests
#
CountCPUs();
-if (!BuildTestAgentd() ||
- !GitPull($Targets) ||
- !BuildWine($Targets, $NoRm, "win32", "") ||
- !BuildWine($Targets, $NoRm, "wow64", "--enable-win64") ||
- !BuildWine($Targets, $NoRm, "wow32", "--with-wine64='$DataDir/build-wow64'"))
+if (!BuildTestAgentd() or
+ !GitPull($Targets) or
+ !UpdateAddOns($Targets) or
+ !BuildWine($Targets, $NoRm, "win32", "") or
+ !BuildWine($Targets, $NoRm, "wow64", "--enable-win64") or
+ !BuildWine($Targets, $NoRm, "wow32", "--with-wine64='$DataDir/build-wow64'") or
+ !NewWinePrefix($Targets, "win32") or
+ # The wow32 and wow64 wineprefixes:
+ # - Are essentially identical.
+ # - Must be created after both WoW builds have been updated.
+ # - Make it possible to run the wow32 and wow64 tests in separate prefixes,
+ # thus ensuring they don't interfere with each other.
+ !NewWinePrefix($Targets, "wow64") or
+ !NewWinePrefix($Targets, "wow32"))
{
exit(1);
}
diff --git a/testbot/bin/build/WineTest.pl b/testbot/bin/build/WineTest.pl
index 3be81485e..518deae99 100755
--- a/testbot/bin/build/WineTest.pl
+++ b/testbot/bin/build/WineTest.pl
@@ -144,6 +144,62 @@ sub BuildWine($$)
}
+#
+# Test helpers
+#
+
+# See also WineReconfig.pl
+sub SetupWineEnvironment($)
+{
+ my ($Build) = @_;
+
+ $ENV{WINEPREFIX} = "$DataDir/wineprefix-$Build";
+ $ENV{DISPLAY} ||= ":0.0";
+}
+
+# See also WineReconfig.pl
+sub RunWine($$$)
+{
+ my ($Build, $Cmd, $CmdArgs) = @_;
+
+ my $Magic = `cd '$DataDir/build-$Build' && file $Cmd`;
+ my $Wine = ($Magic =~ /ELF 64/ ? "./wine64" : "./wine");
+ return system("cd '$DataDir/build-$Build' && set -x && ".
+ "time $Wine $Cmd $CmdArgs");
+}
+
+sub DailyWineTest($$$$)
+{
+ my ($Targets, $Build, $BaseTag, $Args) = @_;
+
+ return 1 if (!$Targets->{$Build});
+
+ InfoMsg "\nRunning WineTest in the $Build Wine\n";
+ SetupWineEnvironment($Build);
+
+ # Run WineTest. Ignore the exit code since it returns non-zero whenever
+ # there are test failures.
+ RunWine($Build, "./programs/winetest/winetest.exe.so",
+ "-c -o '../$Build.report' -t $BaseTag-$Build ". ShArgv2Cmd(@$Args));
+ if (!-f "$Build.report")
+ {
+ LogMsg "WineTest did not produce a report file\n";
+ return 0;
+ }
+
+ # Send the report to the website
+ if ($Targets->{submit} and
+ RunWine($Build, "./programs/winetest/winetest.exe.so",
+ "-c -s '../$Build.report'"))
+ {
+ LogMsg "WineTest failed to send the $Build report\n";
+ # Soldier on in case it's just a network issue
+ }
+
+ return 1;
+}
+
+
#
# Setup and command line processing
#
@@ -152,9 +208,9 @@ $ENV{PATH} = "/usr/lib/ccache:/usr/bin:/bin";
delete $ENV{ENV};
my %AllTargets;
-map { $AllTargets{$_} = 1 } qw(win32 wow32 wow64);
+map { $AllTargets{$_} = 1 } qw(win32 wow32 wow64 submit);
-my ($Usage, $TargetList, $Action, $FileName);
+my ($Usage, $TargetList, $Action, $FileName, $BaseTag);
while (@ARGV)
{
my $Arg = shift @ARGV;
@@ -177,6 +233,12 @@ while (@ARGV)
{
$Action = $Arg;
}
+ elsif (($Action || "") eq "winetest")
+ {
+ $BaseTag = $Arg;
+ # The remaining arguments are meant for WineTest
+ last;
+ }
elsif (!defined $FileName)
{
if (IsValidFileName($Arg))
@@ -230,6 +292,23 @@ if (!defined $Usage)
Error "you must specify the action to perform\n";
$Usage = 2;
}
+ elsif ($Action eq "winetest")
+ {
+ if (!defined $BaseTag)
+ {
+ Error "you must specify a base tag for WineTest\n";
+ $Usage = 2;
+ }
+ elsif ($BaseTag =~ m/^([\w_.\-]+)$/)
+ {
+ $BaseTag = $1;
+ }
+ else
+ {
+ Error "invalid WineTest base tag '$BaseTag'\n";
+ $Usage = 2;
+ }
+ }
elsif ($Action ne "build")
{
Error "invalid '$Action' action\n";
@@ -245,16 +324,23 @@ if (!defined $Usage)
if (defined $Usage)
{
print "Usage: $Name0 [--help] TARGETS build PATCH\n";
+ print "or $Name0 [--help] TARGETS winetest BASETAG ARGS\n";
print "\n";
- print "Applies the specified patch and rebuilds Wine.\n";
+ print "Tests the specified patch or runs WineTest in Wine.\n";
print "\n";
print "Where:\n";
- print " TARGETS Is a comma-separated list of targets for the build.\n";
+ print " TARGETS Is a comma-separated list of targets for the specified action.\n";
print " - win32: The regular 32 bit Wine build.\n";
print " - wow32: The 32 bit WoW Wine build.\n";
print " - wow64: The 64 bit WoW Wine build.\n";
+ print " - submit: Send the WineTest result to the website.\n";
print " build Verify that the patch compiles.\n";
print " PATCH Is the staging file containing the patch to test.\n";
+ print " winetest Run WineTest and submit the result to the website if the submit\n";
+ print " task was specified.\n";
+ print " BASETAG Is the tag for this WineTest run. Note that the build type is\n";
+ print " automatically added to this tag.\n";
+ print " ARGS The WineTest arguments.\n";
print " --help Shows this usage message.\n";
exit $Usage;
}
@@ -267,16 +353,28 @@ if ($DataDir =~ /'/)
#
-# Run the builds
+# Run the builds and tests
#
+# Clean up old reports
+map { unlink("$_.report") } keys %AllTargets;
+
CountCPUs();
-my $Impacts = ApplyPatch($FileName);
-exit(1) if (!$Impacts or
- !BuildWine($Targets, "win32") or
- !BuildWine($Targets, "wow64") or
- !BuildWine($Targets, "wow32"));
+if ($Action eq "build")
+{
+ my $Impacts = ApplyPatch($FileName);
+ exit(1) if (!$Impacts or
+ !BuildWine($Targets, "win32") or
+ !BuildWine($Targets, "wow64") or
+ !BuildWine($Targets, "wow32"));
+}
+elsif ($Action eq "winetest")
+{
+ exit(1) if (!DailyWineTest($Targets, "win32", $BaseTag, \@ARGV) or
+ !DailyWineTest($Targets, "wow64", $BaseTag, \@ARGV) or
+ !DailyWineTest($Targets, "wow32", $BaseTag, \@ARGV));
+}
LogMsg "ok\n";
exit;
diff --git a/testbot/lib/WineTestBot/LogUtils.pm b/testbot/lib/WineTestBot/LogUtils.pm
index 363f80827..2d3042ec7 100644
--- a/testbot/lib/WineTestBot/LogUtils.pm
+++ b/testbot/lib/WineTestBot/LogUtils.pm
@@ -458,6 +458,7 @@ sub GetLogFileNames($;$)
my ($Dir, $IncludeOld) = @_;
my @Candidates = ("exe32.report", "exe64.report",
+ "win32.report", "wow32.report", "wow64.report",
"log", "err");
push @Candidates, "log.old", "err.old" if ($IncludeOld);
@@ -472,10 +473,13 @@ sub GetLogFileNames($;$)
my %_LogFileLabels = (
"exe32.report" => "32 bit Windows report",
"exe64.report" => "64 bit Windows report",
- "err" => "task errors",
+ "win32.report" => "32 bit Wine report",
+ "wow32.report" => "32 bit WoW Wine report",
+ "wow64.report" => "64 bit Wow Wine report",
"log" => "task log",
- "err.old" => "old task errors",
+ "err" => "task errors",
"log.old" => "old logs",
+ "err.old" => "old task errors",
);
=pod
diff --git a/testbot/lib/WineTestBot/Utils.pm b/testbot/lib/WineTestBot/Utils.pm
index 111a56589..f64310b6b 100644
--- a/testbot/lib/WineTestBot/Utils.pm
+++ b/testbot/lib/WineTestBot/Utils.pm
@@ -29,7 +29,7 @@ use Exporter 'import';
our @EXPORT = qw(MakeSecureURL SecureConnection GenerateRandomString
OpenNewFile CreateNewFile CreateNewLink CreateNewDir
DurationToString BuildEMailRecipient IsValidFileName
- ShQuote);
+ ShQuote ShArgv2Cmd);
use Fcntl;
@@ -220,4 +220,21 @@ sub ShQuote($)
return "\"$Str\"";
}
+=pod
+=over 12
+
+=item C<ShArgv2Cmd()>
+
+Converts an argument list into a command line suitable for use in a shell.
+
+See also ShQuote().
+
+=back
+=cut
+
+sub ShArgv2Cmd(@)
+{
+ return join(' ', map { /[^a-zA-Z0-9\/.,+_-]/ ? ShQuote($_) : $_ } @_);
+}
+
1;
--
2.18.0
June 27, 2018