From c2bc47143c1d7fa6b740b7e1ccfbcba12a024b01 Mon Sep 17 00:00:00 2001
From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com>
Date: Tue, 17 Feb 2026 01:58:40 +0000
Subject: [PATCH 01/10] Initial plan
From 9f502f9c7ba1cc71ba2559516e02d575d89d098f Mon Sep 17 00:00:00 2001
From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com>
Date: Tue, 17 Feb 2026 02:29:30 +0000
Subject: [PATCH 02/10] Add FORCE_COLOR environment variable support to
ConsoleUtils and ConsoleLoggerProvider
Co-authored-by: stephentoub <2642209+stephentoub@users.noreply.github.com>
---
.../Common/src/System/Console/ConsoleUtils.cs | 27 +++++++-------
.../src/ConsoleLoggerProvider.cs | 8 ++--
.../src/System/ConsolePal.Unix.cs | 4 +-
src/libraries/System.Console/tests/Color.cs | 37 +++++++++++++------
4 files changed, 46 insertions(+), 30 deletions(-)
diff --git a/src/libraries/Common/src/System/Console/ConsoleUtils.cs b/src/libraries/Common/src/System/Console/ConsoleUtils.cs
index f8472390d1f858..7da5e30a088205 100644
--- a/src/libraries/Common/src/System/Console/ConsoleUtils.cs
+++ b/src/libraries/Common/src/System/Console/ConsoleUtils.cs
@@ -5,7 +5,7 @@ namespace System
{
internal static partial class ConsoleUtils
{
- /// Whether to output ansi color strings.
+ /// Whether to output ANSI color strings.
private static volatile int s_emitAnsiColorCodes = -1;
/// Get whether to emit ANSI color codes.
@@ -13,34 +13,35 @@ public static bool EmitAnsiColorCodes
{
get
{
- // The flag starts at -1. If it's no longer -1, it's 0 or 1 to represent false or true.
+ // The flag starts at -1. If it's no longer -1, it's 0 or 1 to represent false or true.
int emitAnsiColorCodes = s_emitAnsiColorCodes;
if (emitAnsiColorCodes != -1)
{
return Convert.ToBoolean(emitAnsiColorCodes);
}
- // We've not yet computed whether to emit codes or not. Do so now. We may race with
+ // We've not yet computed whether to emit codes or not. We may race with
// other threads, and that's ok; this is idempotent unless someone is currently changing
// the value of the relevant environment variables, in which case behavior here is undefined.
+ // Per https://force-color.org/, FORCE_COLOR forces ANSI color output when set to a non-empty value.
+ // DOTNET_SYSTEM_CONSOLE_ALLOW_ANSI_COLOR_REDIRECTION is treated as a legacy alias for the same behavior.
+ // These take highest priority and override all other checks.
+ if (!string.IsNullOrEmpty(Environment.GetEnvironmentVariable("FORCE_COLOR")) ||
+ !string.IsNullOrEmpty(Environment.GetEnvironmentVariable("DOTNET_SYSTEM_CONSOLE_ALLOW_ANSI_COLOR_REDIRECTION")))
+ {
+ s_emitAnsiColorCodes = 1;
+ return true;
+ }
+
// By default, we emit ANSI color codes if output isn't redirected, and suppress them if output is redirected.
bool enabled = !Console.IsOutputRedirected;
if (enabled)
{
- // We subscribe to the informal standard from https://no-color.org/. If we'd otherwise emit
- // ANSI color codes but the NO_COLOR environment variable is set, disable emitting them.
+ // Per https://no-color.org/, NO_COLOR disables ANSI color output when set.
enabled = Environment.GetEnvironmentVariable("NO_COLOR") is null;
}
- else
- {
- // We also support overriding in the other direction. If we'd otherwise avoid emitting color
- // codes but the DOTNET_SYSTEM_CONSOLE_ALLOW_ANSI_COLOR_REDIRECTION environment variable is
- // set to 1 or true, enable color.
- string? envVar = Environment.GetEnvironmentVariable("DOTNET_SYSTEM_CONSOLE_ALLOW_ANSI_COLOR_REDIRECTION");
- enabled = envVar is not null && (envVar == "1" || envVar.Equals("true", StringComparison.OrdinalIgnoreCase));
- }
// Store and return the computed answer.
s_emitAnsiColorCodes = Convert.ToInt32(enabled);
diff --git a/src/libraries/Microsoft.Extensions.Logging.Console/src/ConsoleLoggerProvider.cs b/src/libraries/Microsoft.Extensions.Logging.Console/src/ConsoleLoggerProvider.cs
index 68a356de9ba748..ff800908a7f438 100644
--- a/src/libraries/Microsoft.Extensions.Logging.Console/src/ConsoleLoggerProvider.cs
+++ b/src/libraries/Microsoft.Extensions.Logging.Console/src/ConsoleLoggerProvider.cs
@@ -68,11 +68,11 @@ public ConsoleLoggerProvider(IOptionsMonitor options, IEnu
[UnsupportedOSPlatformGuard("windows")]
private static bool DoesConsoleSupportAnsi()
{
- string? envVar = Environment.GetEnvironmentVariable("DOTNET_SYSTEM_CONSOLE_ALLOW_ANSI_COLOR_REDIRECTION");
- if (envVar is not null && (envVar == "1" || envVar.Equals("true", StringComparison.OrdinalIgnoreCase)))
+ // Per https://force-color.org/, FORCE_COLOR forces ANSI color output when set to a non-empty value.
+ // DOTNET_SYSTEM_CONSOLE_ALLOW_ANSI_COLOR_REDIRECTION is treated as a legacy alias for the same behavior.
+ if (!string.IsNullOrEmpty(Environment.GetEnvironmentVariable("FORCE_COLOR")) ||
+ !string.IsNullOrEmpty(Environment.GetEnvironmentVariable("DOTNET_SYSTEM_CONSOLE_ALLOW_ANSI_COLOR_REDIRECTION")))
{
- // ANSI color support forcibly enabled via environment variable. This logic matches the behaviour
- // found in System.ConsoleUtils.EmitAnsiColorCodes.
return true;
}
if (
diff --git a/src/libraries/System.Console/src/System/ConsolePal.Unix.cs b/src/libraries/System.Console/src/System/ConsolePal.Unix.cs
index 57d4ef11fd62e3..7440caa7885322 100644
--- a/src/libraries/System.Console/src/System/ConsolePal.Unix.cs
+++ b/src/libraries/System.Console/src/System/ConsolePal.Unix.cs
@@ -1112,8 +1112,8 @@ private static void InvalidateTerminalSettings()
Volatile.Write(ref s_invalidateCachedSettings, 1);
}
- // Ansi colors are enabled when stdout is a terminal or when
- // DOTNET_SYSTEM_CONSOLE_ALLOW_ANSI_COLOR_REDIRECTION is set.
+ // Ansi colors are enabled when stdout is a terminal, when
+ // FORCE_COLOR is set, or when DOTNET_SYSTEM_CONSOLE_ALLOW_ANSI_COLOR_REDIRECTION is set.
// In both cases, they are written to stdout.
internal static void WriteTerminalAnsiColorString(string? value)
=> WriteTerminalAnsiString(value, OpenStandardOutputHandle(), mayChangeCursorPosition: false);
diff --git a/src/libraries/System.Console/tests/Color.cs b/src/libraries/System.Console/tests/Color.cs
index 0c43c50c03b424..b8fbaa7ace6ad8 100644
--- a/src/libraries/System.Console/tests/Color.cs
+++ b/src/libraries/System.Console/tests/Color.cs
@@ -78,16 +78,33 @@ public static bool TermIsSetAndRemoteExecutorIsSupported
[ConditionalTheory(nameof(TermIsSetAndRemoteExecutorIsSupported))]
[PlatformSpecific(TestPlatforms.AnyUnix)]
[SkipOnPlatform(TestPlatforms.Browser | TestPlatforms.iOS | TestPlatforms.MacCatalyst | TestPlatforms.tvOS, "Not supported on Browser, iOS, MacCatalyst, or tvOS.")]
- [InlineData(null)]
- [InlineData("1")]
- [InlineData("true")]
- [InlineData("tRuE")]
- [InlineData("0")]
- [InlineData("false")]
- public static void RedirectedOutput_EnvVarSet_EmitsAnsiCodes(string? envVar)
+ [InlineData("DOTNET_SYSTEM_CONSOLE_ALLOW_ANSI_COLOR_REDIRECTION", "1", null, null, true)]
+ [InlineData("DOTNET_SYSTEM_CONSOLE_ALLOW_ANSI_COLOR_REDIRECTION", "true", null, null, true)]
+ [InlineData("DOTNET_SYSTEM_CONSOLE_ALLOW_ANSI_COLOR_REDIRECTION", "tRuE", null, null, true)]
+ [InlineData("DOTNET_SYSTEM_CONSOLE_ALLOW_ANSI_COLOR_REDIRECTION", "0", null, null, true)]
+ [InlineData("DOTNET_SYSTEM_CONSOLE_ALLOW_ANSI_COLOR_REDIRECTION", "any-value", null, null, true)]
+ [InlineData(null, null, "FORCE_COLOR", "1", true)]
+ [InlineData(null, null, "FORCE_COLOR", "true", true)]
+ [InlineData(null, null, "FORCE_COLOR", "any-value", true)]
+ [InlineData(null, null, "NO_COLOR", "1", false)]
+ [InlineData(null, null, "NO_COLOR", "true", false)]
+ [InlineData(null, null, "NO_COLOR", "any-value", false)]
+ [InlineData("FORCE_COLOR", "1", "NO_COLOR", "1", true)]
+ [InlineData("DOTNET_SYSTEM_CONSOLE_ALLOW_ANSI_COLOR_REDIRECTION", "1", "NO_COLOR", "1", true)]
+ public static void RedirectedOutput_ColorEnvVars_RespectColorPreference(
+ string? envVarName1, string? envVarValue1,
+ string? envVarName2, string? envVarValue2,
+ bool shouldEmitEscapes)
{
var psi = new ProcessStartInfo { RedirectStandardOutput = true };
- psi.Environment["DOTNET_SYSTEM_CONSOLE_ALLOW_ANSI_COLOR_REDIRECTION"] = envVar;
+ if (envVarName1 is not null)
+ {
+ psi.Environment[envVarName1] = envVarValue1;
+ }
+ if (envVarName2 is not null)
+ {
+ psi.Environment[envVarName2] = envVarValue2;
+ }
for (int i = 0; i < 3; i++)
{
@@ -113,13 +130,11 @@ public static void RedirectedOutput_EnvVarSet_EmitsAnsiCodes(string? envVar)
using RemoteInvokeHandle remote = RemoteExecutor.Invoke(main, i.ToString(CultureInfo.InvariantCulture), new RemoteInvokeOptions() { StartInfo = psi });
- bool expectedEscapes = envVar is not null && (envVar == "1" || envVar.Equals("true", StringComparison.OrdinalIgnoreCase));
-
string stdout = remote.Process.StandardOutput.ReadToEnd();
string[] parts = stdout.Split("SEPARATOR");
Assert.Equal(3, parts.Length);
- Assert.Equal(expectedEscapes, parts[1].Contains(Esc));
+ Assert.Equal(shouldEmitEscapes, parts[1].Contains(Esc));
}
}
}
From 961225e002fb8bf1f82469ded8bc3b993df39458 Mon Sep 17 00:00:00 2001
From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com>
Date: Tue, 17 Feb 2026 02:32:23 +0000
Subject: [PATCH 03/10] Fix comment: 'In all cases' instead of 'In both cases'
since there are now three trigger conditions
Co-authored-by: stephentoub <2642209+stephentoub@users.noreply.github.com>
---
src/libraries/System.Console/src/System/ConsolePal.Unix.cs | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/src/libraries/System.Console/src/System/ConsolePal.Unix.cs b/src/libraries/System.Console/src/System/ConsolePal.Unix.cs
index 7440caa7885322..0aef24b28da7c7 100644
--- a/src/libraries/System.Console/src/System/ConsolePal.Unix.cs
+++ b/src/libraries/System.Console/src/System/ConsolePal.Unix.cs
@@ -1114,7 +1114,7 @@ private static void InvalidateTerminalSettings()
// Ansi colors are enabled when stdout is a terminal, when
// FORCE_COLOR is set, or when DOTNET_SYSTEM_CONSOLE_ALLOW_ANSI_COLOR_REDIRECTION is set.
- // In both cases, they are written to stdout.
+ // In all cases, they are written to stdout.
internal static void WriteTerminalAnsiColorString(string? value)
=> WriteTerminalAnsiString(value, OpenStandardOutputHandle(), mayChangeCursorPosition: false);
From 9659c7e1a5b78a78058d400badb73f6a5bf954f7 Mon Sep 17 00:00:00 2001
From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com>
Date: Tue, 17 Feb 2026 03:20:17 +0000
Subject: [PATCH 04/10] Add NO_COLOR support to
ConsoleLoggerProvider.DoesConsoleSupportAnsi
Co-authored-by: stephentoub <2642209+stephentoub@users.noreply.github.com>
---
.../src/ConsoleLoggerProvider.cs | 7 +++++++
1 file changed, 7 insertions(+)
diff --git a/src/libraries/Microsoft.Extensions.Logging.Console/src/ConsoleLoggerProvider.cs b/src/libraries/Microsoft.Extensions.Logging.Console/src/ConsoleLoggerProvider.cs
index ff800908a7f438..f05da9785bd457 100644
--- a/src/libraries/Microsoft.Extensions.Logging.Console/src/ConsoleLoggerProvider.cs
+++ b/src/libraries/Microsoft.Extensions.Logging.Console/src/ConsoleLoggerProvider.cs
@@ -75,6 +75,13 @@ private static bool DoesConsoleSupportAnsi()
{
return true;
}
+
+ // Per https://no-color.org/, NO_COLOR disables ANSI color output when set.
+ if (Environment.GetEnvironmentVariable("NO_COLOR") is not null)
+ {
+ return false;
+ }
+
if (
#if NETFRAMEWORK
Environment.OSVersion.Platform != PlatformID.Win32NT
From 78ee4df365de026a06a774db9f86f928121970dc Mon Sep 17 00:00:00 2001
From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com>
Date: Tue, 17 Feb 2026 08:09:32 +0000
Subject: [PATCH 05/10] Add empty-string test cases and M.E.Logging.Console
tests for color env vars
Co-authored-by: stephentoub <2642209+stephentoub@users.noreply.github.com>
---
.../ConsoleLoggerTest.cs | 37 +++++++++++++++++++
src/libraries/System.Console/tests/Color.cs | 2 +
2 files changed, 39 insertions(+)
diff --git a/src/libraries/Microsoft.Extensions.Logging.Console/tests/Microsoft.Extensions.Logging.Console.Tests/ConsoleLoggerTest.cs b/src/libraries/Microsoft.Extensions.Logging.Console/tests/Microsoft.Extensions.Logging.Console.Tests/ConsoleLoggerTest.cs
index f48a4a0e1176ab..792ace00e97a47 100644
--- a/src/libraries/Microsoft.Extensions.Logging.Console/tests/Microsoft.Extensions.Logging.Console.Tests/ConsoleLoggerTest.cs
+++ b/src/libraries/Microsoft.Extensions.Logging.Console/tests/Microsoft.Extensions.Logging.Console.Tests/ConsoleLoggerTest.cs
@@ -445,6 +445,43 @@ public void AddConsole_IsOutputRedirected_ColorDisabled()
}, new RemoteInvokeOptions { StartInfo = new ProcessStartInfo() { RedirectStandardOutput = true } }).Dispose();
}
+ [ConditionalTheory(nameof(IsThreadingAndRemoteExecutorSupported))]
+ [InlineData("FORCE_COLOR", "1", null, null, "AnsiLogConsole")]
+ [InlineData("DOTNET_SYSTEM_CONSOLE_ALLOW_ANSI_COLOR_REDIRECTION", "1", null, null, "AnsiLogConsole")]
+ [InlineData(null, null, "NO_COLOR", "1", "AnsiParsingLogConsole")]
+ [InlineData("FORCE_COLOR", "1", "NO_COLOR", "1", "AnsiLogConsole")]
+ public void DoesConsoleSupportAnsi_RespectsColorEnvVars(
+ string? envVarName1, string? envVarValue1,
+ string? envVarName2, string? envVarValue2,
+ string expectedConsoleTypeName)
+ {
+ var psi = new ProcessStartInfo { RedirectStandardOutput = true };
+ if (envVarName1 is not null)
+ {
+ psi.Environment[envVarName1] = envVarValue1;
+ }
+ if (envVarName2 is not null)
+ {
+ psi.Environment[envVarName2] = envVarValue2;
+ }
+
+ RemoteExecutor.Invoke(static (expectedTypeName) =>
+ {
+ var loggerProvider = new ServiceCollection()
+ .AddLogging(builder => builder.AddConsole())
+ .BuildServiceProvider()
+ .GetRequiredService();
+
+ var consoleLoggerProvider = Assert.IsType(loggerProvider);
+
+ var messageQueueField = typeof(ConsoleLoggerProvider).GetField("_messageQueue", System.Reflection.BindingFlags.NonPublic | System.Reflection.BindingFlags.Instance);
+ var processor = (ConsoleLoggerProcessor)messageQueueField!.GetValue(consoleLoggerProvider)!;
+ Assert.Equal(expectedTypeName, processor.Console.GetType().Name);
+
+ loggerProvider.Dispose();
+ }, expectedConsoleTypeName, new RemoteInvokeOptions { StartInfo = psi }).Dispose();
+ }
+
[ConditionalFact(typeof(PlatformDetection), nameof(PlatformDetection.IsThreadingSupported))]
public void WriteDebug_LogsCorrectColors()
{
diff --git a/src/libraries/System.Console/tests/Color.cs b/src/libraries/System.Console/tests/Color.cs
index b8fbaa7ace6ad8..8b0f50feaff161 100644
--- a/src/libraries/System.Console/tests/Color.cs
+++ b/src/libraries/System.Console/tests/Color.cs
@@ -83,9 +83,11 @@ public static bool TermIsSetAndRemoteExecutorIsSupported
[InlineData("DOTNET_SYSTEM_CONSOLE_ALLOW_ANSI_COLOR_REDIRECTION", "tRuE", null, null, true)]
[InlineData("DOTNET_SYSTEM_CONSOLE_ALLOW_ANSI_COLOR_REDIRECTION", "0", null, null, true)]
[InlineData("DOTNET_SYSTEM_CONSOLE_ALLOW_ANSI_COLOR_REDIRECTION", "any-value", null, null, true)]
+ [InlineData("DOTNET_SYSTEM_CONSOLE_ALLOW_ANSI_COLOR_REDIRECTION", "", null, null, false)]
[InlineData(null, null, "FORCE_COLOR", "1", true)]
[InlineData(null, null, "FORCE_COLOR", "true", true)]
[InlineData(null, null, "FORCE_COLOR", "any-value", true)]
+ [InlineData(null, null, "FORCE_COLOR", "", false)]
[InlineData(null, null, "NO_COLOR", "1", false)]
[InlineData(null, null, "NO_COLOR", "true", false)]
[InlineData(null, null, "NO_COLOR", "any-value", false)]
From b6179b3228d71f9db5dad7a246eff35d9721d53f Mon Sep 17 00:00:00 2001
From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com>
Date: Tue, 17 Feb 2026 11:50:14 +0000
Subject: [PATCH 06/10] Fix RedirectedOutputDoesNotUseAnsiSequences test to
tolerate extraneous console output from test framework
Co-authored-by: stephentoub <2642209+stephentoub@users.noreply.github.com>
---
src/libraries/System.Console/tests/Color.cs | 5 +++--
1 file changed, 3 insertions(+), 2 deletions(-)
diff --git a/src/libraries/System.Console/tests/Color.cs b/src/libraries/System.Console/tests/Color.cs
index 8b0f50feaff161..e087ddf8a60fc1 100644
--- a/src/libraries/System.Console/tests/Color.cs
+++ b/src/libraries/System.Console/tests/Color.cs
@@ -67,8 +67,9 @@ public static void RedirectedOutputDoesNotUseAnsiSequences()
Console.ResetColor();
Console.Write('4');
- Assert.Equal(0, Encoding.UTF8.GetString(data.ToArray()).ToCharArray().Count(c => c == Esc));
- Assert.Equal("1234", Encoding.UTF8.GetString(data.ToArray()));
+ string outputText = Encoding.UTF8.GetString(data.ToArray());
+ Assert.Equal(0, outputText.Count(c => c == Esc));
+ Assert.StartsWith("1234", outputText);
});
}
From 34d0d304345b2fd2ace1de0f47f47664dbc9dc1c Mon Sep 17 00:00:00 2001
From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com>
Date: Tue, 17 Feb 2026 13:05:11 +0000
Subject: [PATCH 07/10] Fix RedirectedOutputDoesNotUseAnsiSequences: flush
Console.Out before reading and restore exact Assert.Equal
Co-authored-by: stephentoub <2642209+stephentoub@users.noreply.github.com>
---
src/libraries/System.Console/tests/Color.cs | 3 ++-
1 file changed, 2 insertions(+), 1 deletion(-)
diff --git a/src/libraries/System.Console/tests/Color.cs b/src/libraries/System.Console/tests/Color.cs
index e087ddf8a60fc1..d537e9494f5aa6 100644
--- a/src/libraries/System.Console/tests/Color.cs
+++ b/src/libraries/System.Console/tests/Color.cs
@@ -67,9 +67,10 @@ public static void RedirectedOutputDoesNotUseAnsiSequences()
Console.ResetColor();
Console.Write('4');
+ Console.Out.Flush();
string outputText = Encoding.UTF8.GetString(data.ToArray());
Assert.Equal(0, outputText.Count(c => c == Esc));
- Assert.StartsWith("1234", outputText);
+ Assert.Equal("1234", outputText);
});
}
From 0ae627e22b122d972f4c38f75b0d6d9b67b05b20 Mon Sep 17 00:00:00 2001
From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com>
Date: Sat, 28 Feb 2026 10:46:55 +0000
Subject: [PATCH 08/10] Revert RedirectedOutputDoesNotUseAnsiSequences to
original form and fix ConditionalTheory attribute style
Co-authored-by: stephentoub <2642209+stephentoub@users.noreply.github.com>
---
src/libraries/System.Console/tests/Color.cs | 8 +++-----
1 file changed, 3 insertions(+), 5 deletions(-)
diff --git a/src/libraries/System.Console/tests/Color.cs b/src/libraries/System.Console/tests/Color.cs
index 9d56eb61fbabe3..8b0f50feaff161 100644
--- a/src/libraries/System.Console/tests/Color.cs
+++ b/src/libraries/System.Console/tests/Color.cs
@@ -67,17 +67,15 @@ public static void RedirectedOutputDoesNotUseAnsiSequences()
Console.ResetColor();
Console.Write('4');
- Console.Out.Flush();
- string outputText = Encoding.UTF8.GetString(data.ToArray());
- Assert.Equal(0, outputText.Count(c => c == Esc));
- Assert.Equal("1234", outputText);
+ Assert.Equal(0, Encoding.UTF8.GetString(data.ToArray()).ToCharArray().Count(c => c == Esc));
+ Assert.Equal("1234", Encoding.UTF8.GetString(data.ToArray()));
});
}
public static bool TermIsSetAndRemoteExecutorIsSupported
=> !string.IsNullOrEmpty(Environment.GetEnvironmentVariable("TERM")) && RemoteExecutor.IsSupported;
- [ConditionalTheory(typeof(Color), nameof(TermIsSetAndRemoteExecutorIsSupported))]
+ [ConditionalTheory(nameof(TermIsSetAndRemoteExecutorIsSupported))]
[PlatformSpecific(TestPlatforms.AnyUnix)]
[SkipOnPlatform(TestPlatforms.Browser | TestPlatforms.iOS | TestPlatforms.MacCatalyst | TestPlatforms.tvOS, "Not supported on Browser, iOS, MacCatalyst, or tvOS.")]
[InlineData("DOTNET_SYSTEM_CONSOLE_ALLOW_ANSI_COLOR_REDIRECTION", "1", null, null, true)]
From 5f6818671564ff699a6beefe53f69fcc37c64297 Mon Sep 17 00:00:00 2001
From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com>
Date: Sat, 28 Feb 2026 14:38:13 +0000
Subject: [PATCH 09/10] Changes before error encountered
Co-authored-by: stephentoub <2642209+stephentoub@users.noreply.github.com>
---
src/libraries/System.Console/tests/Color.cs | 26 +++++++++++----------
1 file changed, 14 insertions(+), 12 deletions(-)
diff --git a/src/libraries/System.Console/tests/Color.cs b/src/libraries/System.Console/tests/Color.cs
index 8b0f50feaff161..6b57d5b7ae8b40 100644
--- a/src/libraries/System.Console/tests/Color.cs
+++ b/src/libraries/System.Console/tests/Color.cs
@@ -51,31 +51,33 @@ public static void BackgroundColor_Throws_PlatformNotSupportedException()
Assert.Throws(() => Console.BackgroundColor = ConsoleColor.Red);
}
- [Fact]
+ [ConditionalFact(typeof(RemoteExecutor), nameof(RemoteExecutor.IsSupported))]
[SkipOnPlatform(TestPlatforms.Browser | TestPlatforms.iOS | TestPlatforms.MacCatalyst | TestPlatforms.tvOS, "Not supported on Browser, iOS, MacCatalyst, or tvOS.")]
public static void RedirectedOutputDoesNotUseAnsiSequences()
{
- // Make sure that redirecting to a memory stream causes Console not to write out the ANSI sequences
-
- Helpers.RunInRedirectedOutput((data) =>
+ // Run in a child process with redirected stdout so that no in-process
+ // test framework output (e.g. xunit skip messages) can pollute the stream.
+ var startInfo = new ProcessStartInfo { RedirectStandardOutput = true };
+ using RemoteInvokeHandle handle = RemoteExecutor.Invoke(static () =>
{
- Console.Write('1');
+ Console.Write("1");
Console.ForegroundColor = ConsoleColor.Blue;
- Console.Write('2');
+ Console.Write("2");
Console.BackgroundColor = ConsoleColor.Red;
- Console.Write('3');
+ Console.Write("3");
Console.ResetColor();
- Console.Write('4');
+ Console.Write("4");
+ }, new RemoteInvokeOptions { StartInfo = startInfo });
- Assert.Equal(0, Encoding.UTF8.GetString(data.ToArray()).ToCharArray().Count(c => c == Esc));
- Assert.Equal("1234", Encoding.UTF8.GetString(data.ToArray()));
- });
+ string capturedOutput = handle.Process.StandardOutput.ReadToEnd();
+ Assert.DoesNotContain(Esc.ToString(), capturedOutput);
+ Assert.Equal("1234", capturedOutput);
}
public static bool TermIsSetAndRemoteExecutorIsSupported
=> !string.IsNullOrEmpty(Environment.GetEnvironmentVariable("TERM")) && RemoteExecutor.IsSupported;
- [ConditionalTheory(nameof(TermIsSetAndRemoteExecutorIsSupported))]
+ [ConditionalTheory(typeof(Color), nameof(TermIsSetAndRemoteExecutorIsSupported))]
[PlatformSpecific(TestPlatforms.AnyUnix)]
[SkipOnPlatform(TestPlatforms.Browser | TestPlatforms.iOS | TestPlatforms.MacCatalyst | TestPlatforms.tvOS, "Not supported on Browser, iOS, MacCatalyst, or tvOS.")]
[InlineData("DOTNET_SYSTEM_CONSOLE_ALLOW_ANSI_COLOR_REDIRECTION", "1", null, null, true)]
From 4161212488e357310a160d3fe9ac2ca06b286a2c Mon Sep 17 00:00:00 2001
From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com>
Date: Sun, 1 Mar 2026 17:43:20 +0000
Subject: [PATCH 10/10] Changes before error encountered
Co-authored-by: stephentoub <2642209+stephentoub@users.noreply.github.com>
---
src/libraries/System.Console/tests/Color.cs | 19 +++++++++++++++++++
1 file changed, 19 insertions(+)
diff --git a/src/libraries/System.Console/tests/Color.cs b/src/libraries/System.Console/tests/Color.cs
index 6b57d5b7ae8b40..520ebadde8366c 100644
--- a/src/libraries/System.Console/tests/Color.cs
+++ b/src/libraries/System.Console/tests/Color.cs
@@ -60,6 +60,8 @@ public static void RedirectedOutputDoesNotUseAnsiSequences()
var startInfo = new ProcessStartInfo { RedirectStandardOutput = true };
using RemoteInvokeHandle handle = RemoteExecutor.Invoke(static () =>
{
+ Console.Error.WriteLine($"IsOutputRedirected: {Console.IsOutputRedirected}");
+ Console.Error.WriteLine($"TERM: {Environment.GetEnvironmentVariable("TERM")}");
Console.Write("1");
Console.ForegroundColor = ConsoleColor.Blue;
Console.Write("2");
@@ -67,9 +69,26 @@ public static void RedirectedOutputDoesNotUseAnsiSequences()
Console.Write("3");
Console.ResetColor();
Console.Write("4");
+ Console.Error.WriteLine($"Done writing");
}, new RemoteInvokeOptions { StartInfo = startInfo });
string capturedOutput = handle.Process.StandardOutput.ReadToEnd();
+ byte[] rawBytes = System.Text.Encoding.UTF8.GetBytes(capturedOutput);
+ Console.Error.WriteLine($"Output length: {rawBytes.Length}");
+ Console.Error.WriteLine($"Output hex: {BitConverter.ToString(rawBytes)}");
+ Console.Error.Write("Output chars: ");
+ foreach (char c in capturedOutput)
+ {
+ if (c >= 32 && c < 127)
+ Console.Error.Write(c);
+ else
+ Console.Error.Write($"[0x{(int)c:X2}]");
+ }
+ Console.Error.WriteLine();
+ Console.Error.WriteLine($"capturedOutput[0] = 0x{(int)capturedOutput[0]:X2}");
+ Console.Error.WriteLine($"capturedOutput == \"1234\": {capturedOutput == "1234"}");
+ Console.Error.WriteLine($"Contains ESC: {capturedOutput.Contains(Esc)}");
+ Console.Error.WriteLine($"Esc char value: 0x{(int)Esc:X2}");
Assert.DoesNotContain(Esc.ToString(), capturedOutput);
Assert.Equal("1234", capturedOutput);
}