Skip to content

Commit 33742df

Browse files
committed
Integration tests perf
1 parent 803c90b commit 33742df

File tree

6 files changed

+119
-207
lines changed

6 files changed

+119
-207
lines changed

test/IntegrationTests/MSTest.Acceptance.IntegrationTests/Program.cs

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,6 @@
88
// Opt-out telemetry
99
Environment.SetEnvironmentVariable("DOTNET_CLI_TELEMETRY_OPTOUT", "1");
1010

11-
CommandLine.MaxOutstandingCommands = Environment.ProcessorCount;
1211
DotnetCli.DoNotRetry = Debugger.IsAttached;
1312

1413
ITestApplicationBuilder builder = await TestApplication.CreateBuilderAsync(args);
@@ -29,5 +28,4 @@ CompositeExtensionFactory<SlowestTestsConsumer> slowestTestCompositeServiceFacto
2928
builder.TestHost.AddTestSessionLifetimeHandle(slowestTestCompositeServiceFactory);
3029
using ITestApplication app = await builder.BuildAsync();
3130
int returnValue = await app.RunAsync();
32-
Console.WriteLine($"Process started: {CommandLine.TotalProcessesAttempt}");
3331
return returnValue;

test/IntegrationTests/Microsoft.Testing.Platform.Acceptance.IntegrationTests/Program.cs

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,6 @@
88
// Opt-out telemetry
99
Environment.SetEnvironmentVariable("DOTNET_CLI_TELEMETRY_OPTOUT", "1");
1010

11-
CommandLine.MaxOutstandingCommands = Environment.ProcessorCount;
1211
DotnetCli.DoNotRetry = Debugger.IsAttached;
1312

1413
ITestApplicationBuilder builder = await TestApplication.CreateBuilderAsync(args);
@@ -30,5 +29,4 @@ CompositeExtensionFactory<SlowestTestsConsumer> slowestTestCompositeServiceFacto
3029
builder.TestHost.AddTestSessionLifetimeHandle(slowestTestCompositeServiceFactory);
3130
using ITestApplication app = await builder.BuildAsync();
3231
int returnValue = await app.RunAsync();
33-
Console.WriteLine($"Process started: {CommandLine.TotalProcessesAttempt}");
3432
return returnValue;

test/Utilities/Microsoft.Testing.TestInfrastructure/CommandLine.cs

Lines changed: 14 additions & 42 deletions
Original file line numberDiff line numberDiff line change
@@ -7,13 +7,6 @@ namespace Microsoft.Testing.TestInfrastructure;
77

88
public sealed class CommandLine : IDisposable
99
{
10-
private static int s_totalProcessesAttempt;
11-
[SuppressMessage("Style", "IDE0032:Use auto property", Justification = "It's causing some runtime issue")]
12-
private static int s_maxOutstandingCommand = Environment.ProcessorCount;
13-
private static SemaphoreSlim s_maxOutstandingCommands_semaphore = new(s_maxOutstandingCommand, s_maxOutstandingCommand);
14-
15-
public static int TotalProcessesAttempt => s_totalProcessesAttempt;
16-
1710
private readonly List<string> _errorOutputLines = [];
1811
private readonly List<string> _standardOutputLines = [];
1912
private IProcessHandle? _process;
@@ -26,18 +19,6 @@ public sealed class CommandLine : IDisposable
2619

2720
public string ErrorOutput => string.Join(Environment.NewLine, _errorOutputLines);
2821

29-
public static int MaxOutstandingCommands
30-
{
31-
get => s_maxOutstandingCommand;
32-
33-
set
34-
{
35-
s_maxOutstandingCommand = value;
36-
s_maxOutstandingCommands_semaphore.Dispose();
37-
s_maxOutstandingCommands_semaphore = new SemaphoreSlim(s_maxOutstandingCommand, s_maxOutstandingCommand);
38-
}
39-
}
40-
4122
public async Task RunAsync(
4223
string commandLine,
4324
IDictionary<string, string?>? environmentVariables = null,
@@ -75,30 +56,21 @@ public async Task<int> RunAsyncAndReturnExitCodeAsync(
7556
bool cleanDefaultEnvironmentVariableIfCustomAreProvided = false,
7657
CancellationToken cancellationToken = default)
7758
{
78-
await s_maxOutstandingCommands_semaphore.WaitAsync(cancellationToken);
79-
try
80-
{
81-
Interlocked.Increment(ref s_totalProcessesAttempt);
82-
(string command, string arguments) = GetCommandAndArguments(commandLine);
83-
_errorOutputLines.Clear();
84-
_standardOutputLines.Clear();
85-
ProcessConfiguration startInfo = new(command)
86-
{
87-
Arguments = arguments,
88-
EnvironmentVariables = environmentVariables,
89-
OnErrorOutput = (_, o) => _errorOutputLines.Add(ClearBOM(o)),
90-
OnStandardOutput = (_, o) => _standardOutputLines.Add(ClearBOM(o)),
91-
WorkingDirectory = workingDirectory,
92-
};
93-
_process = ProcessFactory.Start(startInfo, cleanDefaultEnvironmentVariableIfCustomAreProvided);
94-
95-
using CancellationTokenRegistration registration = cancellationToken.Register(() => _process.Kill());
96-
return await _process.WaitForExitAsync(cancellationToken);
97-
}
98-
finally
59+
(string command, string arguments) = GetCommandAndArguments(commandLine);
60+
_errorOutputLines.Clear();
61+
_standardOutputLines.Clear();
62+
ProcessConfiguration startInfo = new(command)
9963
{
100-
s_maxOutstandingCommands_semaphore.Release();
101-
}
64+
Arguments = arguments,
65+
EnvironmentVariables = environmentVariables,
66+
OnErrorOutput = (_, o) => _errorOutputLines.Add(ClearBOM(o)),
67+
OnStandardOutput = (_, o) => _standardOutputLines.Add(ClearBOM(o)),
68+
WorkingDirectory = workingDirectory,
69+
};
70+
_process = ProcessFactory.Start(startInfo, cleanDefaultEnvironmentVariableIfCustomAreProvided);
71+
72+
using CancellationTokenRegistration registration = cancellationToken.Register(() => _process.Kill());
73+
return await _process.WaitForExitAsync(cancellationToken);
10274
}
10375

10476
/// <summary>

test/Utilities/Microsoft.Testing.TestInfrastructure/DotnetCli.cs

Lines changed: 43 additions & 67 deletions
Original file line numberDiff line numberDiff line change
@@ -29,22 +29,6 @@ public static class DotnetCli
2929

3030
private static int s_binlogCounter;
3131

32-
[SuppressMessage("Style", "IDE0032:Use auto property", Justification = "It's causing some runtime bug")]
33-
private static int s_maxOutstandingCommand = Environment.ProcessorCount;
34-
private static SemaphoreSlim s_maxOutstandingCommands_semaphore = new(s_maxOutstandingCommand, s_maxOutstandingCommand);
35-
36-
public static int MaxOutstandingCommands
37-
{
38-
get => s_maxOutstandingCommand;
39-
40-
set
41-
{
42-
s_maxOutstandingCommand = value;
43-
s_maxOutstandingCommands_semaphore.Dispose();
44-
s_maxOutstandingCommands_semaphore = new SemaphoreSlim(s_maxOutstandingCommand, s_maxOutstandingCommand);
45-
}
46-
}
47-
4832
public static bool DoNotRetry { get; set; }
4933

5034
public static async Task<DotnetMuxerResult> RunAsync(
@@ -61,69 +45,61 @@ public static async Task<DotnetMuxerResult> RunAsync(
6145
[CallerMemberName] string callerMemberName = "",
6246
CancellationToken cancellationToken = default)
6347
{
64-
await s_maxOutstandingCommands_semaphore.WaitAsync(cancellationToken);
65-
try
48+
environmentVariables ??= [];
49+
foreach (DictionaryEntry entry in Environment.GetEnvironmentVariables())
6650
{
67-
environmentVariables ??= [];
68-
foreach (DictionaryEntry entry in Environment.GetEnvironmentVariables())
51+
// Skip all unwanted environment variables.
52+
string? key = entry.Key.ToString();
53+
if (WellKnownEnvironmentVariables.ToSkipEnvironmentVariables.Contains(key, StringComparer.OrdinalIgnoreCase))
6954
{
70-
// Skip all unwanted environment variables.
71-
string? key = entry.Key.ToString();
72-
if (WellKnownEnvironmentVariables.ToSkipEnvironmentVariables.Contains(key, StringComparer.OrdinalIgnoreCase))
73-
{
74-
continue;
75-
}
55+
continue;
56+
}
7657

77-
if (disableCodeCoverage)
58+
if (disableCodeCoverage)
59+
{
60+
// Disable the code coverage during the build.
61+
if (CodeCoverageEnvironmentVariables.Contains(key, StringComparer.OrdinalIgnoreCase))
7862
{
79-
// Disable the code coverage during the build.
80-
if (CodeCoverageEnvironmentVariables.Contains(key, StringComparer.OrdinalIgnoreCase))
81-
{
82-
continue;
83-
}
63+
continue;
8464
}
85-
86-
// We use TryAdd to let tests "overwrite" existing environment variables.
87-
// Consider that the given dictionary has "TESTINGPLATFORM_UI_LANGUAGE" as a key.
88-
// And also Environment.GetEnvironmentVariables() is returning TESTINGPLATFORM_UI_LANGUAGE.
89-
// In that case, we do a "TryAdd" which effectively means the value from the original dictionary wins.
90-
environmentVariables.TryAdd(key!, entry.Value!.ToString()!);
9165
}
9266

93-
if (disableTelemetry)
94-
{
95-
environmentVariables.Add("DOTNET_CLI_TELEMETRY_OPTOUT", "1");
96-
}
67+
// We use TryAdd to let tests "overwrite" existing environment variables.
68+
// Consider that the given dictionary has "TESTINGPLATFORM_UI_LANGUAGE" as a key.
69+
// And also Environment.GetEnvironmentVariables() is returning TESTINGPLATFORM_UI_LANGUAGE.
70+
// In that case, we do a "TryAdd" which effectively means the value from the original dictionary wins.
71+
environmentVariables.TryAdd(key!, entry.Value!.ToString()!);
72+
}
73+
74+
if (disableTelemetry)
75+
{
76+
environmentVariables.Add("DOTNET_CLI_TELEMETRY_OPTOUT", "1");
77+
}
9778

98-
environmentVariables["NUGET_PACKAGES"] = nugetGlobalPackagesFolder;
79+
environmentVariables["NUGET_PACKAGES"] = nugetGlobalPackagesFolder;
9980

100-
string extraArgs = warnAsError ? " -p:MSBuildTreatWarningsAsErrors=true" : string.Empty;
101-
extraArgs += suppressPreviewDotNetMessage ? " -p:SuppressNETCoreSdkPreviewMessage=true" : string.Empty;
102-
if (args.IndexOf("-- ", StringComparison.Ordinal) is int platformArgsIndex && platformArgsIndex > 0)
103-
{
104-
args = args.Insert(platformArgsIndex, extraArgs + " ");
105-
}
106-
else
107-
{
108-
args += extraArgs;
109-
}
81+
string extraArgs = warnAsError ? " -p:MSBuildTreatWarningsAsErrors=true" : string.Empty;
82+
extraArgs += suppressPreviewDotNetMessage ? " -p:SuppressNETCoreSdkPreviewMessage=true" : string.Empty;
83+
if (args.IndexOf("-- ", StringComparison.Ordinal) is int platformArgsIndex && platformArgsIndex > 0)
84+
{
85+
args = args.Insert(platformArgsIndex, extraArgs + " ");
86+
}
87+
else
88+
{
89+
args += extraArgs;
90+
}
11091

111-
if (DoNotRetry)
112-
{
113-
return await CallTheMuxerAsync(args, environmentVariables, workingDirectory, failIfReturnValueIsNotZero, callerMemberName, cancellationToken);
114-
}
115-
else
116-
{
117-
IEnumerable<TimeSpan> delay = Backoff.ExponentialBackoff(TimeSpan.FromSeconds(3), retryCount, factor: 1.5);
118-
return await Policy
119-
.Handle<Exception>()
120-
.WaitAndRetryAsync(delay)
121-
.ExecuteAsync(async ct => await CallTheMuxerAsync(args, environmentVariables, workingDirectory, failIfReturnValueIsNotZero, callerMemberName, ct), cancellationToken);
122-
}
92+
if (DoNotRetry)
93+
{
94+
return await CallTheMuxerAsync(args, environmentVariables, workingDirectory, failIfReturnValueIsNotZero, callerMemberName, cancellationToken);
12395
}
124-
finally
96+
else
12597
{
126-
s_maxOutstandingCommands_semaphore.Release();
98+
IEnumerable<TimeSpan> delay = Backoff.ExponentialBackoff(TimeSpan.FromSeconds(3), retryCount, factor: 1.5);
99+
return await Policy
100+
.Handle<Exception>()
101+
.WaitAndRetryAsync(delay)
102+
.ExecuteAsync(async ct => await CallTheMuxerAsync(args, environmentVariables, workingDirectory, failIfReturnValueIsNotZero, callerMemberName, ct), cancellationToken);
127103
}
128104
}
129105

test/Utilities/Microsoft.Testing.TestInfrastructure/ProcessFactory.cs

Lines changed: 16 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -61,27 +61,29 @@ public static IProcessHandle Start(ProcessConfiguration config, bool cleanDefaul
6161
process.Exited += (s, e) => config.OnExit.Invoke(processHandle, process.ExitCode);
6262
}
6363

64-
if (config.OnStandardOutput != null)
65-
{
66-
process.OutputDataReceived += (s, e) =>
64+
_ = Task.Factory.StartNew(
65+
() =>
6766
{
68-
if (!string.IsNullOrWhiteSpace(e.Data))
67+
while (process.StandardOutput.ReadLine() is string line)
6968
{
70-
config.OnStandardOutput(processHandle, e.Data);
69+
if (!string.IsNullOrWhiteSpace(line))
70+
{
71+
config.OnStandardOutput?.Invoke(processHandle, line);
72+
}
7173
}
72-
};
73-
}
74+
}, TaskCreationOptions.LongRunning);
7475

75-
if (config.OnErrorOutput != null)
76-
{
77-
process.ErrorDataReceived += (s, e) =>
76+
_ = Task.Factory.StartNew(
77+
() =>
7878
{
79-
if (!string.IsNullOrWhiteSpace(e.Data))
79+
while (process.StandardError.ReadLine() is string line)
8080
{
81-
config.OnErrorOutput(processHandle, e.Data);
81+
if (!string.IsNullOrWhiteSpace(line))
82+
{
83+
config.OnErrorOutput?.Invoke(processHandle, line);
84+
}
8285
}
83-
};
84-
}
86+
}, TaskCreationOptions.LongRunning);
8587

8688
if (!process.Start())
8789
{
@@ -100,16 +102,6 @@ public static IProcessHandle Start(ProcessConfiguration config, bool cleanDefaul
100102

101103
processHandleInfo.Id = process.Id;
102104

103-
if (config.OnStandardOutput != null)
104-
{
105-
process.BeginOutputReadLine();
106-
}
107-
108-
if (config.OnErrorOutput != null)
109-
{
110-
process.BeginErrorReadLine();
111-
}
112-
113105
return processHandle;
114106
}
115107
}

0 commit comments

Comments
 (0)