From 2f13414dd17b1686a619abd9432a77ab4af03d40 Mon Sep 17 00:00:00 2001 From: Michael Simons Date: Fri, 12 Jun 2026 10:07:34 -0500 Subject: [PATCH 1/2] Fix flaky SubLevelCommandNameShouldBeSentToTelemetry test on macOS The test was intermittently failing on macOS arm64 because it used the static Parser.RootCommand which can be mutated by other tests. InstantiateCommand.ExecuteAsync dynamically adds template names (e.g. 'console') as subcommands to the static parser tree. When this mutation occurs before the telemetry test runs, 'console' is classified as TokenType.Command instead of TokenType.Argument, causing the test to fail. Fix by parsing against a fresh DotNetCommandDefinition instance which is guaranteed to not have dynamically-added template subcommands. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> --- test/dotnet.Tests/TelemetryTests/TelemetryFilterTest.cs | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/test/dotnet.Tests/TelemetryTests/TelemetryFilterTest.cs b/test/dotnet.Tests/TelemetryTests/TelemetryFilterTest.cs index 300f1f90e0e1..aba260dd7de0 100644 --- a/test/dotnet.Tests/TelemetryTests/TelemetryFilterTest.cs +++ b/test/dotnet.Tests/TelemetryTests/TelemetryFilterTest.cs @@ -1,6 +1,7 @@ // Licensed to the .NET Foundation under one or more agreements. // The .NET Foundation licenses this file to you under the MIT license. +using Microsoft.DotNet.Cli.Commands; using Microsoft.DotNet.Cli.Telemetry; using Microsoft.DotNet.Cli.Utils; using Microsoft.DotNet.Utilities; @@ -52,7 +53,11 @@ public void TopLevelCommandNameShouldBeSentToTelemetryWithGlobalJsonState() [Fact] public void SubLevelCommandNameShouldBeSentToTelemetry() { - var parseResult = Parser.Parse(["new", "console"]); + // Use a fresh DotNetCommandDefinition to avoid test pollution from + // other tests that may have dynamically added template names (e.g. "console") + // as subcommands to the static Parser.RootCommand's "new" command. + // See InstantiateCommand.ExecuteAsync which mutates the static parser tree. + var parseResult = new DotNetCommandDefinition().Parse(["new", "console"], Parser.ParserConfiguration); TelemetryEventEntry.SendFiltered(parseResult); _fakeTelemetry .LogEntries.Should() From 8ffcc4ca0cafdb9c47f719ff6f30afbaf462d5aa Mon Sep 17 00:00:00 2001 From: Michael Simons Date: Fri, 12 Jun 2026 12:37:52 -0500 Subject: [PATCH 2/2] Fix duplicate --version option in telemetry test Remove the built-in VersionOption from the fresh DotNetCommandDefinition before parsing. DotNetCommandDefinition extends RootCommand which adds a default --version option, and the DotNetCommandDefinition constructor adds its own custom one. In production, Parser.NormalizeRootOptions (private) handles this removal, so the test must replicate that step. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> --- .../TelemetryTests/TelemetryFilterTest.cs | 13 ++++++++++++- 1 file changed, 12 insertions(+), 1 deletion(-) diff --git a/test/dotnet.Tests/TelemetryTests/TelemetryFilterTest.cs b/test/dotnet.Tests/TelemetryTests/TelemetryFilterTest.cs index aba260dd7de0..8e5f306888a9 100644 --- a/test/dotnet.Tests/TelemetryTests/TelemetryFilterTest.cs +++ b/test/dotnet.Tests/TelemetryTests/TelemetryFilterTest.cs @@ -1,6 +1,7 @@ // Licensed to the .NET Foundation under one or more agreements. // The .NET Foundation licenses this file to you under the MIT license. +using System.CommandLine; using Microsoft.DotNet.Cli.Commands; using Microsoft.DotNet.Cli.Telemetry; using Microsoft.DotNet.Cli.Utils; @@ -57,7 +58,17 @@ public void SubLevelCommandNameShouldBeSentToTelemetry() // other tests that may have dynamically added template names (e.g. "console") // as subcommands to the static Parser.RootCommand's "new" command. // See InstantiateCommand.ExecuteAsync which mutates the static parser tree. - var parseResult = new DotNetCommandDefinition().Parse(["new", "console"], Parser.ParserConfiguration); + var rootCommand = new DotNetCommandDefinition(); + // Remove the built-in VersionOption that conflicts with the SDK's custom --version option. + // In production, Parser.NormalizeRootOptions handles this, but it's private. + for (int i = rootCommand.Options.Count - 1; i >= 0; i--) + { + if (rootCommand.Options[i] is VersionOption) + { + rootCommand.Options.RemoveAt(i); + } + } + var parseResult = rootCommand.Parse(["new", "console"], Parser.ParserConfiguration); TelemetryEventEntry.SendFiltered(parseResult); _fakeTelemetry .LogEntries.Should()