Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -111,12 +111,23 @@ private void InitializeOutput(int degreeOfParallelism, ParseResult parseResult,
// TODO: Replace this with proper CI detection that we already have in telemetry. https://github.com/microsoft/testfx/issues/5533#issuecomment-2838893327
bool inCI = string.Equals(Environment.GetEnvironmentVariable("TF_BUILD"), "true", StringComparison.OrdinalIgnoreCase) || string.Equals(Environment.GetEnvironmentVariable("GITHUB_ACTIONS"), "true", StringComparison.OrdinalIgnoreCase);

AnsiMode ansiMode = AnsiMode.AnsiIfPossible;
if (noAnsi)
{
// User explicitly specified --no-ansi.
// We should respect that.
ansiMode = AnsiMode.NoAnsi;
}
else if (inCI)
{
ansiMode = AnsiMode.SimpleAnsi;
}

_output = new TerminalTestReporter(console, new TerminalTestReporterOptions()
{
ShowPassedTests = showPassedTests,
ShowProgress = !noProgress,
UseAnsi = !noAnsi,
UseCIAnsi = inCI,
AnsiMode = ansiMode,
ShowAssembly = true,
ShowAssemblyStartAndComplete = true,
MinimumExpectedTests = parseResult.GetValue(definition.MinimumExpectedTestsOption),
Expand Down
38 changes: 22 additions & 16 deletions src/Cli/dotnet/Commands/Test/MTP/Terminal/TerminalTestReporter.cs
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
// Licensed under the MIT license. See LICENSE file in the project root for full license information.

using System.Collections.Concurrent;
using System.Diagnostics;
using System.Globalization;
using System.Text.RegularExpressions;
using Microsoft.CodeAnalysis;
Expand Down Expand Up @@ -70,27 +71,32 @@ public TerminalTestReporter(IConsole console, TerminalTestReporterOptions option
int nonAnsiUpdateCadenceInMs = 3_000;
// When writing to ANSI we update the progress in place and it should look responsive so we update every half second, because we only show seconds on the screen, so it is good enough.
int ansiUpdateCadenceInMs = 500;
if (!_options.UseAnsi)

if (_options.AnsiMode == AnsiMode.SimpleAnsi)
{
terminalWithProgress = new TestProgressStateAwareTerminal(new NonAnsiTerminal(console), _options.ShowProgress, writeProgressImmediatelyAfterOutput: false, updateEvery: nonAnsiUpdateCadenceInMs);
// We are told externally that we are in CI, use simplified ANSI mode.
terminalWithProgress = new TestProgressStateAwareTerminal(new SimpleAnsiTerminal(console), _options.ShowProgress, writeProgressImmediatelyAfterOutput: true, updateEvery: nonAnsiUpdateCadenceInMs);
}
else
{
if (_options.UseCIAnsi)
{
// We are told externally that we are in CI, use simplified ANSI mode.
terminalWithProgress = new TestProgressStateAwareTerminal(new SimpleAnsiTerminal(console), _options.ShowProgress, writeProgressImmediatelyAfterOutput: true, updateEvery: nonAnsiUpdateCadenceInMs);
}
else
// We are not in CI, or in CI non-compatible with simple ANSI, autodetect terminal capabilities
// Autodetect.
(bool consoleAcceptsAnsiCodes, bool _, uint? originalConsoleMode) = NativeMethods.QueryIsScreenAndTryEnableAnsiColorCodes();
_originalConsoleMode = originalConsoleMode;

bool useAnsi = _options.AnsiMode switch
{
// We are not in CI, or in CI non-compatible with simple ANSI, autodetect terminal capabilities
// Autodetect.
(bool consoleAcceptsAnsiCodes, bool _, uint? originalConsoleMode) = NativeMethods.QueryIsScreenAndTryEnableAnsiColorCodes();
_originalConsoleMode = originalConsoleMode;
terminalWithProgress = consoleAcceptsAnsiCodes
? new TestProgressStateAwareTerminal(new AnsiTerminal(console, _options.BaseDirectory), _options.ShowProgress, writeProgressImmediatelyAfterOutput: true, updateEvery: ansiUpdateCadenceInMs)
: new TestProgressStateAwareTerminal(new NonAnsiTerminal(console), _options.ShowProgress, writeProgressImmediatelyAfterOutput: false, updateEvery: nonAnsiUpdateCadenceInMs);
}
AnsiMode.ForceAnsi => true,
AnsiMode.NoAnsi => false,
AnsiMode.AnsiIfPossible => consoleAcceptsAnsiCodes,
_ => throw new UnreachableException(),
};

terminalWithProgress = new TestProgressStateAwareTerminal(
useAnsi ? new AnsiTerminal(console, _options.BaseDirectory) : new NonAnsiTerminal(console),
_options.ShowProgress,
writeProgressImmediatelyAfterOutput: useAnsi,
updateEvery: useAnsi ? ansiUpdateCadenceInMs : nonAnsiUpdateCadenceInMs);
}

_terminalWithProgress = terminalWithProgress;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -41,13 +41,32 @@ internal sealed class TerminalTestReporterOptions
public bool ShowActiveTests { get; init; }

/// <summary>
/// Gets a value indicating whether we should use ANSI escape codes or disable them. When true the capabilities of the console are autodetected.
/// Gets a value indicating the ANSI mode.
/// </summary>
public bool UseAnsi { get; init; }
public AnsiMode AnsiMode { get; init; }
}

internal enum AnsiMode
{
/// <summary>
/// Disable ANSI escape codes.
/// </summary>
NoAnsi,

/// <summary>
/// Use simplified ANSI renderer, which colors output, but does not move cursor.
/// This is used in compatible CI environments.
/// </summary>
SimpleAnsi,

/// <summary>
/// Enable ANSI escape codes, including cursor movement, when the capabilities of the console allow it.
/// </summary>
AnsiIfPossible,

/// <summary>
/// Gets a value indicating whether we are running in compatible CI, and should use simplified ANSI renderer, which colors output, but does not move cursor.
/// Setting <see cref="UseAnsi"/> to false will disable this option.
/// Force ANSI escape codes, regardless of the capabilities of the console.
/// This is needed only for testing.
/// </summary>
public bool UseCIAnsi { get; init; }
ForceAnsi,
}