Skip to content

Commit 5a978c2

Browse files
authored
Set dotnet-watch timeout based on XUnitWorkItemTimeout (#40028)
1 parent b42b4a6 commit 5a978c2

File tree

8 files changed

+49
-40
lines changed

8 files changed

+49
-40
lines changed

src/Tasks/Microsoft.NET.Build.Extensions.Tasks.UnitTests/Microsoft.NET.Build.Extensions.Tasks.UnitTests.csproj

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -24,11 +24,12 @@
2424

2525
<ItemGroup>
2626
<ProjectReference Include="..\Microsoft.NET.Build.Extensions.Tasks\Microsoft.NET.Build.Extensions.Tasks.csproj" />
27+
<ProjectReference Include="..\..\..\test\Microsoft.NET.TestFramework\Microsoft.NET.TestFramework.csproj" />
2728
</ItemGroup>
2829

2930
<ItemGroup>
3031
<Compile Include="**\*.cs" />
31-
<Compile Include="..\..\..\test\Common\Program.UnitTests.cs" />
32+
<Compile Include="..\..\..\test\Common\Program.cs" />
3233
<Compile Include="..\Microsoft.NET.Build.Tasks.UnitTests\Mocks\MockBuildEngine.cs" />
3334
<Compile Include="..\Microsoft.NET.Build.Tasks.UnitTests\Mocks\MockTaskItem.cs" />
3435
</ItemGroup>

src/Tasks/Microsoft.NET.Build.Tasks.UnitTests/Microsoft.NET.Build.Tasks.UnitTests.csproj

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -35,7 +35,7 @@
3535

3636
<ItemGroup>
3737
<Compile Include="**\*.cs" />
38-
<Compile Include="..\..\..\test\Common\Program.UnitTests.cs" />
38+
<Compile Include="..\..\..\test\Common\Program.cs" />
3939
</ItemGroup>
4040

4141
<ItemGroup>

test/Common/Program.UnitTests.cs

Lines changed: 0 additions & 24 deletions
This file was deleted.

test/Common/Program.cs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,7 @@
11
// Licensed to the .NET Foundation under one or more agreements.
22
// The .NET Foundation licenses this file to you under the MIT license.
3+
using Microsoft.NET.TestFramework;
4+
using Microsoft.NET.TestFramework.Commands;
35

46
#pragma warning disable SA1205 // Partial elements should declare access
57
partial class Program

test/HelixTasks/SDKCustomCreateXUnitWorkItemsWithTestExclusion.cs

Lines changed: 16 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -104,6 +104,14 @@ private async Task<List<ITaskItem>> PrepareWorkItem(ITaskItem xunitProject)
104104
xunitProject.TryGetMetadata("ExcludeAdditionalParameters", out string ExcludeAdditionalParameters);
105105

106106
xunitProject.TryGetMetadata("Arguments", out string arguments);
107+
TimeSpan timeout = TimeSpan.FromMinutes(5);
108+
if (!string.IsNullOrEmpty(XUnitWorkItemTimeout))
109+
{
110+
if (!TimeSpan.TryParse(XUnitWorkItemTimeout, out timeout))
111+
{
112+
Log.LogWarning($"Invalid value \"{XUnitWorkItemTimeout}\" provided for XUnitWorkItemTimeout; falling back to default value of \"00:05:00\" (5 minutes)");
113+
}
114+
}
107115

108116
string assemblyName = Path.GetFileName(targetPath);
109117

@@ -142,24 +150,21 @@ private async Task<List<ITaskItem>> PrepareWorkItem(ITaskItem xunitProject)
142150
var partitionedWorkItem = new List<ITaskItem>();
143151
foreach (var assemblyPartitionInfo in assemblyPartitionInfos)
144152
{
145-
string command = $"{driver} exec {assemblyName} {testExecutionDirectory} {msbuildAdditionalSdkResolverFolder} {(XUnitArguments != null ? " " + XUnitArguments : "")} -xml testResults.xml {assemblyPartitionInfo.ClassListArgumentString} {arguments}";
153+
string command;
146154
if (netFramework)
147155
{
148156
var testFilter = string.IsNullOrEmpty(assemblyPartitionInfo.ClassListArgumentString) ? "" : $"--filter \"{assemblyPartitionInfo.ClassListArgumentString}\"";
149-
command = $"{driver} test {assemblyName} {testExecutionDirectory} {msbuildAdditionalSdkResolverFolder} {(XUnitArguments != null ? " " + XUnitArguments : "")} --results-directory .\\ --logger trx {testFilter}";
157+
command = $"{driver} test {assemblyName} -e HELIX_WORK_ITEM_TIMEOUT={timeout} {testExecutionDirectory} {msbuildAdditionalSdkResolverFolder} " +
158+
$"{(XUnitArguments != null ? " " + XUnitArguments : "")} --results-directory .\\ --logger trx {testFilter}";
150159
}
151-
152-
Log.LogMessage($"Creating work item with properties Identity: {assemblyName}, PayloadDirectory: {publishDirectory}, Command: {command}");
153-
154-
TimeSpan timeout = TimeSpan.FromMinutes(5);
155-
if (!string.IsNullOrEmpty(XUnitWorkItemTimeout))
160+
else
156161
{
157-
if (!TimeSpan.TryParse(XUnitWorkItemTimeout, out timeout))
158-
{
159-
Log.LogWarning($"Invalid value \"{XUnitWorkItemTimeout}\" provided for XUnitWorkItemTimeout; falling back to default value of \"00:05:00\" (5 minutes)");
160-
}
162+
command = $"{driver} exec {assemblyName} -e HELIX_WORK_ITEM_TIMEOUT={timeout} {testExecutionDirectory} {msbuildAdditionalSdkResolverFolder} " +
163+
$"{(XUnitArguments != null ? " " + XUnitArguments : "")} -xml testResults.xml {assemblyPartitionInfo.ClassListArgumentString} {arguments}";
161164
}
162165

166+
Log.LogMessage($"Creating work item with properties Identity: {assemblyName}, PayloadDirectory: {publishDirectory}, Command: {command}");
167+
163168
partitionedWorkItem.Add(new Microsoft.Build.Utilities.TaskItem(assemblyPartitionInfo.DisplayName + testIdentityDifferentiator, new Dictionary<string, string>()
164169
{
165170
{ "Identity", assemblyPartitionInfo.DisplayName + testIdentityDifferentiator},

test/Microsoft.NET.TestFramework/TestCommandLine.cs

Lines changed: 18 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -29,7 +29,9 @@ public class TestCommandLine
2929

3030
public string MsbuildAdditionalSdkResolverFolder { get; set; }
3131

32-
public List<string> TestConfigFiles { get; private set; } = new List<string>();
32+
public List<(string name, string value)> EnvironmentVariables { get; set; } = [];
33+
34+
public List<string> TestConfigFiles { get; private set; } = [];
3335

3436
public HashSet<string> TestListsToRun { get; private set; } = new HashSet<string>(StringComparer.OrdinalIgnoreCase);
3537

@@ -91,6 +93,10 @@ public static TestCommandLine Parse(string[] args)
9193
{
9294
ret.TestListsToRun.Add(argStack.Pop());
9395
}
96+
else if (arg.Equals("-e", StringComparison.CurrentCultureIgnoreCase))
97+
{
98+
ret.EnvironmentVariables.Add(ParseEnvironmentVariableArg(argStack.Pop()));
99+
}
94100
else if (arg.Equals("-showSdkInfo", StringComparison.CurrentCultureIgnoreCase))
95101
{
96102
ret.ShowSdkInfo = true;
@@ -125,6 +131,17 @@ public static TestCommandLine Parse(string[] args)
125131
return ret;
126132
}
127133

134+
private static (string name, string value) ParseEnvironmentVariableArg(string arg)
135+
{
136+
var i = arg.IndexOf('=');
137+
if (i <= 0)
138+
{
139+
throw new ArgumentException($"Invalid environment variable specification (expected 'name=value'): '{arg}'");
140+
}
141+
142+
return (arg.Substring(0, i), arg.Substring(i + 1));
143+
}
144+
128145
public List<string> GetXunitArgsFromTestConfig()
129146
{
130147
List<TestSpecifier> testsToSkip = new();

test/Microsoft.NET.TestFramework/TestContext.cs

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -74,6 +74,11 @@ public static void Initialize(TestCommandLine commandLine)
7474
CommandLoggingContext.SetVerbose(true);
7575
Reporter.Reset();
7676

77+
foreach (var (name, value) in commandLine.EnvironmentVariables)
78+
{
79+
Environment.SetEnvironmentVariable(name, value);
80+
}
81+
7782
Environment.SetEnvironmentVariable("DOTNET_MULTILEVEL_LOOKUP", "0");
7883

7984
// Reset this environment variable so that if the dotnet under test is different than the

test/dotnet-watch.Tests/Utilities/AwaitableProcess.cs

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,10 @@ namespace Microsoft.DotNet.Watcher.Tools
88
{
99
internal class AwaitableProcess : IDisposable
1010
{
11+
// cancel just before we hit timeout used on CI (XUnitWorkItemTimeout value in sdk\test\UnitTests.proj)
12+
private static readonly TimeSpan s_timeout = Environment.GetEnvironmentVariable("HELIX_WORK_ITEM_TIMEOUT") is { } value
13+
? TimeSpan.Parse(value).Subtract(TimeSpan.FromSeconds(10)) : TimeSpan.FromMinutes(1);
14+
1115
private readonly object _testOutputLock = new();
1216

1317
private Process _process;
@@ -70,8 +74,7 @@ public async Task<string> GetOutputLineAsync(Predicate<string> success, Predicat
7074
{
7175
using var cancellationOnFailure = new CancellationTokenSource();
7276

73-
// cancel just before we hit 2 minute time out used on CI (sdk\test\UnitTests.proj)
74-
cancellationOnFailure.CancelAfter(TimeSpan.FromSeconds(110));
77+
cancellationOnFailure.CancelAfter(s_timeout);
7578

7679
var failedLineCount = 0;
7780
while (!_source.Completion.IsCompleted && failedLineCount == 0)

0 commit comments

Comments
 (0)