Skip to content

Commit 64f04db

Browse files
authored
TerminalTestReporter: Use executionId as dictionary key (#50134)
1 parent 623e0c9 commit 64f04db

File tree

3 files changed

+42
-19
lines changed

3 files changed

+42
-19
lines changed

src/Cli/dotnet/Commands/Test/Terminal/TerminalTestReporter.cs

Lines changed: 35 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -45,6 +45,8 @@ internal event EventHandler OnProgressStopUpdate
4545

4646
private readonly TestProgressStateAwareTerminal _terminalWithProgress;
4747

48+
private int _handshakeFailuresCount;
49+
4850
private readonly uint? _originalConsoleMode;
4951
private bool _isDiscovery;
5052
private bool _isHelp;
@@ -59,6 +61,8 @@ internal event EventHandler OnProgressStopUpdate
5961

6062
private bool? _shouldShowPassedTests;
6163

64+
public bool HasHandshakeFailure => _handshakeFailuresCount > 0;
65+
6266
#if NET7_0_OR_GREATER
6367
// Specifying no timeout, the regex is linear. And the timeout does not measure the regex only, but measures also any
6468
// thread suspends, so the regex gets blamed incorrectly.
@@ -168,7 +172,7 @@ public void TestExecutionStarted(DateTimeOffset testStartTime, int workerCount,
168172
_terminalWithProgress.StartShowingProgress(workerCount);
169173
}
170174

171-
public void AssemblyRunStarted(string assembly, string? targetFramework, string? architecture, string? executionId)
175+
public void AssemblyRunStarted(string assembly, string? targetFramework, string? architecture, string executionId)
172176
{
173177
var assemblyRun = GetOrAddAssemblyRun(assembly, targetFramework, architecture, executionId);
174178
assemblyRun.TryCount++;
@@ -197,10 +201,9 @@ public void AssemblyRunStarted(string assembly, string? targetFramework, string?
197201
}
198202
}
199203

200-
private TestProgressState GetOrAddAssemblyRun(string assembly, string? targetFramework, string? architecture, string? executionId)
204+
private TestProgressState GetOrAddAssemblyRun(string assembly, string? targetFramework, string? architecture, string executionId)
201205
{
202-
string key = $"{assembly}|{targetFramework}|{architecture}|{executionId}";
203-
return _assemblies.GetOrAdd(key, _ =>
206+
return _assemblies.GetOrAdd(executionId, _ =>
204207
{
205208
IStopwatch sw = CreateStopwatch();
206209
var assemblyRun = new TestProgressState(Interlocked.Increment(ref _counter), assembly, targetFramework, architecture, sw);
@@ -280,7 +283,7 @@ private void AppendTestRunSummary(ITerminal terminal, int? exitCode)
280283
bool notEnoughTests = totalTests < _options.MinimumExpectedTests;
281284
bool allTestsWereSkipped = totalTests == 0 || totalTests == totalSkippedTests;
282285
bool anyTestFailed = totalFailedTests > 0;
283-
bool anyAssemblyFailed = _assemblies.Values.Any(a => !a.Success);
286+
bool anyAssemblyFailed = _assemblies.Values.Any(a => !a.Success) || HasHandshakeFailure;
284287
bool runFailed = anyAssemblyFailed || anyTestFailed || notEnoughTests || allTestsWereSkipped || _wasCancelled;
285288
terminal.SetColor(runFailed ? TerminalColor.DarkRed : TerminalColor.DarkGreen);
286289

@@ -335,7 +338,7 @@ private void AppendTestRunSummary(ITerminal terminal, int? exitCode)
335338
int passed = _assemblies.Values.Sum(t => t.PassedTests);
336339
int skipped = _assemblies.Values.Sum(t => t.SkippedTests);
337340
int retried = _assemblies.Values.Sum(t => t.RetriedFailedTests);
338-
int error = _assemblies.Values.Sum(t => !t.Success && (t.TotalTests == 0 || t.FailedTests == 0) ? 1 : 0);
341+
int error = _assemblies.Values.Sum(t => !t.Success && (t.TotalTests == 0 || t.FailedTests == 0) ? 1 : 0) + _handshakeFailuresCount;
339342
TimeSpan runDuration = _testExecutionStartTime != null && _testExecutionEndTime != null ? (_testExecutionEndTime - _testExecutionStartTime).Value : TimeSpan.Zero;
340343

341344
bool colorizeFailed = failed > 0;
@@ -454,7 +457,7 @@ internal void TestCompleted(
454457
string assembly,
455458
string? targetFramework,
456459
string? architecture,
457-
string? executionId,
460+
string executionId,
458461
string instanceId,
459462
string testNodeUid,
460463
string displayName,
@@ -467,7 +470,7 @@ internal void TestCompleted(
467470
string? standardOutput,
468471
string? errorOutput)
469472
{
470-
TestProgressState asm = _assemblies[$"{assembly}|{targetFramework}|{architecture}|{executionId}"];
473+
TestProgressState asm = _assemblies[executionId];
471474
var attempt = asm.TryCount;
472475

473476
if (_options.ShowActiveTests)
@@ -797,12 +800,12 @@ private static void AppendIndentedLine(ITerminal terminal, string? message, stri
797800
}
798801
}
799802

800-
internal void AssemblyRunCompleted(string assembly, string? targetFramework, string? architecture, string? executionId,
803+
internal void AssemblyRunCompleted(string executionId,
801804
// These parameters are useful only for "remote" runs in dotnet test, where we are reporting on multiple processes.
802805
// In single process run, like with testing platform .exe we report these via messages, and run exit.
803-
int? exitCode, string? outputData, string? errorData)
806+
int exitCode, string? outputData, string? errorData)
804807
{
805-
TestProgressState assemblyRun = GetOrAddAssemblyRun(assembly, targetFramework, architecture, executionId);
808+
TestProgressState assemblyRun = _assemblies[executionId];
806809
assemblyRun.ExitCode = exitCode;
807810
assemblyRun.Success = exitCode == 0 && assemblyRun.FailedTests == 0;
808811
assemblyRun.Stopwatch.Stop();
@@ -814,7 +817,7 @@ internal void AssemblyRunCompleted(string assembly, string? targetFramework, str
814817
_terminalWithProgress.WriteToTerminal(terminal => AppendAssemblySummary(assemblyRun, terminal));
815818
}
816819

817-
if (exitCode is null or 0)
820+
if (exitCode == 0)
818821
{
819822
// Report nothing, we don't want to report on success, because then we will also report on test-discovery etc.
820823
return;
@@ -826,6 +829,22 @@ internal void AssemblyRunCompleted(string assembly, string? targetFramework, str
826829
});
827830
}
828831

832+
internal void HandshakeFailure(string assemblyPath, string targetFramework, int exitCode, string outputData, string errorData)
833+
{
834+
Interlocked.Increment(ref _handshakeFailuresCount);
835+
_terminalWithProgress.WriteToTerminal(terminal =>
836+
{
837+
terminal.ResetColor();
838+
AppendAssemblyLinkTargetFrameworkAndArchitecture(terminal, assemblyPath, targetFramework, architecture: null);
839+
terminal.Append(' ');
840+
terminal.SetColor(TerminalColor.DarkRed);
841+
terminal.Append(CliCommandStrings.ZeroTestsRan);
842+
terminal.ResetColor();
843+
terminal.AppendLine();
844+
AppendExecutableSummary(terminal, exitCode, outputData, errorData);
845+
});
846+
}
847+
829848
private static void AppendExecutableSummary(ITerminal terminal, int? exitCode, string? outputData, string? errorData)
830849
{
831850
terminal.Append(CliCommandStrings.ExitCode);
@@ -936,11 +955,11 @@ internal void TestDiscovered(
936955
string assembly,
937956
string? targetFramework,
938957
string? architecture,
939-
string? executionId,
958+
string executionId,
940959
string? displayName,
941960
string? uid)
942961
{
943-
TestProgressState asm = _assemblies[$"{assembly}|{targetFramework}|{architecture}|{executionId}"];
962+
TestProgressState asm = _assemblies[executionId];
944963

945964
// TODO: add mode for discovered tests to the progress bar - jajares
946965
asm.DiscoverTest(displayName, uid);
@@ -1028,9 +1047,9 @@ public void TestInProgress(
10281047
string testNodeUid,
10291048
string instanceId,
10301049
string displayName,
1031-
string? executionId)
1050+
string executionId)
10321051
{
1033-
TestProgressState asm = _assemblies[$"{assembly}|{targetFramework}|{architecture}|{executionId}"];
1052+
TestProgressState asm = _assemblies[executionId];
10341053

10351054
if (_options.ShowActiveTests)
10361055
{

src/Cli/dotnet/Commands/Test/TestApplicationEventHandlers.cs

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,8 @@ internal sealed class TestApplicationsEventHandlers(TerminalTestReporter output)
1313
private readonly ConcurrentDictionary<TestApplication, (string ModulePath, string TargetFramework, string Architecture, string ExecutionId)> _executions = new();
1414
private readonly TerminalTestReporter _output = output;
1515

16+
public bool HasHandshakeFailure => _output.HasHandshakeFailure;
17+
1618
public void OnHandshakeReceived(object sender, HandshakeArgs args)
1719
{
1820
var hostType = args.Handshake.Properties[HandshakeMessagePropertyNames.HostType];
@@ -145,11 +147,11 @@ public void OnTestProcessExited(object sender, TestProcessExitEventArgs args)
145147

146148
if (_executions.TryGetValue(testApplication, out var appInfo))
147149
{
148-
_output.AssemblyRunCompleted(appInfo.ModulePath, appInfo.TargetFramework, appInfo.Architecture, appInfo.ExecutionId, args.ExitCode, string.Join(Environment.NewLine, args.OutputData), string.Join(Environment.NewLine, args.ErrorData));
150+
_output.AssemblyRunCompleted(appInfo.ExecutionId, args.ExitCode, string.Join(Environment.NewLine, args.OutputData), string.Join(Environment.NewLine, args.ErrorData));
149151
}
150152
else
151153
{
152-
_output.AssemblyRunCompleted(testApplication.Module.TargetPath ?? testApplication.Module.ProjectFullPath, testApplication.Module.TargetFramework, architecture: null, null, args.ExitCode, string.Join(Environment.NewLine, args.OutputData), string.Join(Environment.NewLine, args.ErrorData));
154+
_output.HandshakeFailure(testApplication.Module.TargetPath ?? testApplication.Module.ProjectFullPath, testApplication.Module.TargetFramework, args.ExitCode, string.Join(Environment.NewLine, args.OutputData), string.Join(Environment.NewLine, args.ErrorData));
153155
}
154156

155157
LogTestProcessExit(args);

src/Cli/dotnet/Commands/Test/TestingPlatformCommand.cs

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -80,7 +80,9 @@ private int RunInternal(ParseResult parseResult)
8080
}
8181

8282
_actionQueue.EnqueueCompleted();
83-
return _actionQueue.WaitAllActions();
83+
var exitCode = _actionQueue.WaitAllActions();
84+
// Don't inline exitCode variable. We want to always call WaitAllActions first.
85+
return _eventHandlers.HasHandshakeFailure ? ExitCode.GenericFailure : exitCode;
8486
}
8587

8688
private void PrepareEnvironment(ParseResult parseResult, out TestOptions testOptions, out int degreeOfParallelism)

0 commit comments

Comments
 (0)