Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
44 commits
Select commit Hold shift + click to select a range
2dd803c
Update dependencies for 10.0.2 Microsoft build and then update depend…
marcpopMSFT Jan 16, 2026
a39c37b
Update dependencies from https://github.com/microsoft/testfx build 20…
dotnet-maestro[bot] Jan 17, 2026
9e7257e
Update dependencies from https://github.com/microsoft/testfx build 20…
dotnet-maestro[bot] Jan 17, 2026
dcff850
Update dependencies from https://github.com/microsoft/testfx build 20…
dotnet-maestro[bot] Jan 18, 2026
230cf7a
Update dependencies from https://github.com/microsoft/testfx build 20…
dotnet-maestro[bot] Jan 18, 2026
0bbf22b
Add GetTagHelpers method to TagHelperDescriptor
marcpopMSFT Jan 18, 2026
6623d93
Change GetTagHelpers method to return TagHelperCollection
marcpopMSFT Jan 18, 2026
171977b
[release/10.0.1xx] Update dependencies from microsoft/testfx (#52521)
DonnaChen888 Jan 19, 2026
1c9e5f5
Update dependencies from https://github.com/microsoft/testfx build 20…
dotnet-maestro[bot] Jan 19, 2026
3a0defd
Update dependencies from https://github.com/microsoft/testfx build 20…
dotnet-maestro[bot] Jan 19, 2026
5a915c0
Refactor StaticTagHelperFeature constructor and methods
marcpopMSFT Jan 19, 2026
a963fc4
Refactor tag helper registration and retrieval
marcpopMSFT Jan 19, 2026
c08a02a
[release/10.0.1xx] Update dependencies from microsoft/testfx (#52536)
DonnaChen888 Jan 19, 2026
4230707
Reset files to release/10.0.2xx
github-actions[bot] Jan 19, 2026
b1daedb
Merge branch 'release/10.0.2xx' into darc-release/10.0.2xx-f1357dab-7…
DonnaChen888 Jan 19, 2026
fdfdde2
Refactor GetTagHelpers method and improve tag helper handling
marcpopMSFT Jan 19, 2026
d8aa6fd
[release/10.0.2xx] Update dependencies from microsoft/testfx (#52522)
DonnaChen888 Jan 19, 2026
e44a9bf
Merge branch 'release/10.0.2xx' into merge/release/10.0.1xx-to-releas…
DonnaChen888 Jan 19, 2026
e41a21b
[release/10.0.2xx] Adjust MTP exit code logic (#52543)
github-actions[bot] Jan 19, 2026
9400f24
[release/10.0.2xx] Handle assemblies gracefully (#52508)
github-actions[bot] Jan 19, 2026
70b0739
[release/10.0.2xx] Refactor ANSI handling for better readability (#52…
github-actions[bot] Jan 19, 2026
424ecf8
Merge branch 'release/10.0.2xx' into merge/release/10.0.1xx-to-releas…
DonnaChen888 Jan 20, 2026
739bba4
Skip DotnetCliSnapshotTests due to known issue
marcpopMSFT Jan 15, 2026
1de6761
add missing details from the package spec
nkolev92 Jan 13, 2026
99ed5a4
[release/10.0.2xx] [dotnet test MTP]: Only use test progress when ANS…
github-actions[bot] Jan 20, 2026
d452413
Adjust expected diagnostics in DisposableObjectInErrorCode_NotDispose…
ericstj Jan 15, 2026
c85001d
Fix another restore section in assets file
ericstj Jan 15, 2026
a264aaa
Fix path to razor source-generated files in StaticWebAssets tests
ericstj Jan 15, 2026
b6db0de
Update test baselines
marcpopMSFT Jan 20, 2026
9a6cfe8
Disable watch test as it's broken by a Roslyn change
marcpopMSFT Jan 20, 2026
26247c1
[release/10.0.2xx] Bump analysislevel constants for .NET 10 release (…
baronfel Jan 20, 2026
17e74d4
Disable an additional watch test
marcpopMSFT Jan 20, 2026
0957156
Workaround: Fix setting checksum algorithm when mapping projects (#52…
tmat Jan 20, 2026
1348752
[automated] Merge branch 'release/10.0.1xx' => 'release/10.0.2xx' (#5…
MiYanni Jan 21, 2026
99ee676
Update dependencies to the Jan release of the runtime (#52513)
marcpopMSFT Jan 21, 2026
597002e
Reset files to release/10.0.3xx
github-actions[bot] Jan 21, 2026
35de6b3
Merge branch 'release/10.0.3xx' into merge/release/10.0.2xx-to-releas…
DonnaChen888 Jan 21, 2026
f06921e
Merge branch 'release/10.0.3xx' into merge/release/10.0.2xx-to-releas…
DonnaChen888 Jan 22, 2026
9829e9f
Merge branch 'release/10.0.3xx' into merge/release/10.0.2xx-to-releas…
DonnaChen888 Jan 22, 2026
334e5e9
Fix errors from version changes. Not sure why these were changed to b…
MiYanni Jan 23, 2026
8daf5ce
Merge branch 'release/10.0.3xx' into merge/release/10.0.2xx-to-releas…
DonnaChen888 Jan 23, 2026
c381890
Merge branch 'release/10.0.3xx' into merge/release/10.0.2xx-to-releas…
DonnaChen888 Jan 26, 2026
1f3fc10
Merge branch 'release/10.0.3xx' of https://github.com/dotnet/sdk into…
DonnaChen888 Jan 29, 2026
11253ae
Merge branch 'release/10.0.3xx' into merge/release/10.0.2xx-to-releas…
marcpopMSFT Jan 29, 2026
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
20 changes: 18 additions & 2 deletions src/BuiltInTools/Watch/HotReload/IncrementalMSBuildWorkspace.cs
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@

using System.Collections.Immutable;
using System.Diagnostics;
using System.Reflection;
using Microsoft.CodeAnalysis;
using Microsoft.CodeAnalysis.ExternalAccess.HotReload.Api;
using Microsoft.CodeAnalysis.Host.Mef;
Expand Down Expand Up @@ -76,7 +77,7 @@ public async Task UpdateProjectConeAsync(string rootProjectPath, CancellationTok
continue;
}

newSolution = HotReloadService.WithProjectInfo(newSolution, ProjectInfo.Create(
newSolution = HotReloadService.WithProjectInfo(newSolution, WithChecksumAlgorithm(ProjectInfo.Create(
oldProjectId,
newProjectInfo.Version,
newProjectInfo.Name,
Expand All @@ -93,7 +94,8 @@ public async Task UpdateProjectConeAsync(string rootProjectPath, CancellationTok
MapDocuments(oldProjectId, newProjectInfo.AdditionalDocuments),
isSubmission: false,
hostObjectType: null,
outputRefFilePath: newProjectInfo.OutputRefFilePath)
outputRefFilePath: newProjectInfo.OutputRefFilePath),
GetChecksumAlgorithm(newProjectInfo))
.WithAnalyzerConfigDocuments(MapDocuments(oldProjectId, newProjectInfo.AnalyzerConfigDocuments))
.WithCompilationOutputInfo(newProjectInfo.CompilationOutputInfo));
}
Expand Down Expand Up @@ -122,6 +124,20 @@ ImmutableArray<DocumentInfo> MapDocuments(ProjectId mappedProjectId, IReadOnlyLi
}).ToImmutableArray();
}

// TODO: remove
// workaround for https://github.com/dotnet/roslyn/pull/82051

private static MethodInfo? s_withChecksumAlgorithm;
private static PropertyInfo? s_getChecksumAlgorithm;

private static ProjectInfo WithChecksumAlgorithm(ProjectInfo info, SourceHashAlgorithm algorithm)
=> (ProjectInfo)(s_withChecksumAlgorithm ??= typeof(ProjectInfo).GetMethod("WithChecksumAlgorithm", BindingFlags.NonPublic | BindingFlags.Instance)!)
.Invoke(info, [algorithm])!;

private static SourceHashAlgorithm GetChecksumAlgorithm(ProjectInfo info)
=> (SourceHashAlgorithm)(s_getChecksumAlgorithm ??= typeof(ProjectInfo).GetProperty("ChecksumAlgorithm", BindingFlags.NonPublic | BindingFlags.Instance)!)
.GetValue(info)!;

public async ValueTask UpdateFileContentAsync(IEnumerable<ChangedFile> changedFiles, CancellationToken cancellationToken)
{
var updatedSolution = CurrentSolution;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -80,7 +80,13 @@ private int RunInternal(ParseResult parseResult, bool isHelp)
actionQueue.EnqueueCompleted();
// Don't inline exitCode variable. We want to always call WaitAllActions first.
var exitCode = actionQueue.WaitAllActions();
exitCode = _output.HasHandshakeFailure ? ExitCode.GenericFailure : exitCode;

// If all test apps exited with 0 exit code, but we detected that handshake didn't happen correctly, map that to generic failure.
if (exitCode == ExitCode.Success && _output.HasHandshakeFailure)
{
exitCode = ExitCode.GenericFailure;
}

if (exitCode == ExitCode.Success &&
parseResult.HasOption(definition.MinimumExpectedTestsOption) &&
parseResult.GetValue(definition.MinimumExpectedTestsOption) is { } minimumExpectedTests &&
Expand All @@ -105,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
43 changes: 21 additions & 22 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 @@ -64,36 +65,34 @@ internal sealed partial class TerminalTestReporter : IDisposable
public TerminalTestReporter(IConsole console, TerminalTestReporterOptions options)
{
_options = options;
TestProgressStateAwareTerminal terminalWithProgress;
bool showProgress = _options.ShowProgress;

// When not writing to ANSI we write the progress to screen and leave it there so we don't want to write it more often than every few seconds.
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)
ITerminal terminal;
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.
terminal = new SimpleAnsiTerminal(console);
showProgress = false;
}
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.NoAnsi => false,
AnsiMode.AnsiIfPossible => consoleAcceptsAnsiCodes,
_ => throw new UnreachableException(),
};

showProgress = showProgress && useAnsi;
terminal = useAnsi ? new AnsiTerminal(console, _options.BaseDirectory) : new NonAnsiTerminal(console);
}

_terminalWithProgress = terminalWithProgress;
_terminalWithProgress = new TestProgressStateAwareTerminal(terminal, showProgress);
}

public void TestExecutionStarted(DateTimeOffset testStartTime, int workerCount, bool isDiscovery, bool isHelp, bool isRetry)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,8 @@ internal sealed class TerminalTestReporterOptions
public int MinimumExpectedTests { get; init; }

/// <summary>
/// Gets a value indicating whether we should write the progress periodically to screen. When ANSI is allowed we update the progress as often as we can. When ANSI is not allowed we update it every 3 seconds.
/// Gets a value indicating whether we should write the progress periodically to screen. When ANSI is allowed we update the progress as often as we can.
/// When ANSI is not allowed we never have progress.
/// </summary>
public bool ShowProgress { get; init; }

Expand All @@ -41,13 +42,26 @@ 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>
/// 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.
/// Enable ANSI escape codes, including cursor movement, when the capabilities of the console allow it.
/// </summary>
public bool UseCIAnsi { get; init; }
AnsiIfPossible,
}
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ namespace Microsoft.DotNet.Cli.Commands.Test.Terminal;
/// <summary>
/// Terminal that updates the progress in place when progress reporting is enabled.
/// </summary>
internal sealed partial class TestProgressStateAwareTerminal(ITerminal terminal, bool showProgress, bool writeProgressImmediatelyAfterOutput, int updateEvery) : IDisposable
internal sealed partial class TestProgressStateAwareTerminal(ITerminal terminal, bool showProgress) : IDisposable
{
/// <summary>
/// A cancellation token to signal the rendering thread that it should exit.
Expand All @@ -20,8 +20,6 @@ internal sealed partial class TestProgressStateAwareTerminal(ITerminal terminal,

private readonly ITerminal _terminal = terminal;
private readonly bool _showProgress = showProgress;
private readonly bool _writeProgressImmediatelyAfterOutput = writeProgressImmediatelyAfterOutput;
private readonly int _updateEvery = updateEvery;
private TestProgressState?[] _progressItems = [];

/// <summary>
Expand All @@ -37,7 +35,11 @@ private void ThreadProc()
{
try
{
while (!_cts.Token.WaitHandle.WaitOne(_updateEvery))
// 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.
// When writing to non-ANSI, we never show progress as the output can get long and messy.
const int AnsiUpdateCadenceInMs = 500;
while (!_cts.Token.WaitHandle.WaitOne(AnsiUpdateCadenceInMs))
{
lock (_lock)
{
Expand Down Expand Up @@ -118,10 +120,7 @@ internal void WriteToTerminal(Action<ITerminal> write)
_terminal.StartUpdate();
_terminal.EraseProgress();
write(_terminal);
if (_writeProgressImmediatelyAfterOutput)
{
_terminal.RenderProgress(_progressItems);
}
_terminal.RenderProgress(_progressItems);
}
finally
{
Expand Down
6 changes: 5 additions & 1 deletion src/Cli/dotnet/Commands/Test/MTP/TestApplicationHandler.cs
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ internal sealed class TestApplicationHandler
private readonly Dictionary<string, (int TestSessionStartCount, int TestSessionEndCount)> _testSessionEventCountPerSessionUid = new();

private (string? TargetFramework, string? Architecture, string ExecutionId)? _handshakeInfo;
private bool _receivedTestHostHandshake;

public TestApplicationHandler(TerminalTestReporter output, TestModule module, TestOptions options)
{
Expand Down Expand Up @@ -62,6 +63,7 @@ internal void OnHandshakeReceived(HandshakeMessage handshakeMessage, bool gotSup
// https://github.com/microsoft/testfx/blob/2a9a353ec2bb4ce403f72e8ba1f29e01e7cf1fd4/src/Platform/Microsoft.Testing.Platform/Hosts/CommonTestHost.cs#L87-L97
if (hostType == "TestHost")
{
_receivedTestHostHandshake = true;
// AssemblyRunStarted counts "retry count", and writes to terminal "(Try <number-of-try>) Running tests from <assembly>"
// So, we want to call it only for test host, and not for test host controller (or orchestrator, if in future it will handshake as well)
// Calling it for both test host and test host controllers means we will count retries incorrectly, and will messages twice.
Expand Down Expand Up @@ -263,8 +265,10 @@ internal bool HasMismatchingTestSessionEventCount()

internal void OnTestProcessExited(int exitCode, string outputData, string errorData)
{
if (_handshakeInfo.HasValue)
if (_receivedTestHostHandshake && _handshakeInfo.HasValue)
{
// If we received a handshake from TestHostController but not from TestHost,
// call HandshakeFailure instead of AssemblyRunCompleted
_output.AssemblyRunCompleted(_handshakeInfo.Value.ExecutionId, exitCode, outputData, errorData);
}
else
Expand Down
1 change: 0 additions & 1 deletion src/RazorSdk/Tool/GenerateCommand.cs
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,6 @@

using System.Collections.Immutable;
using System.Diagnostics;
using System.Threading;
using Microsoft.AspNetCore.Razor.Language;
using Microsoft.CodeAnalysis.CSharp;
using Microsoft.NET.Sdk.Razor.Tool.CommandLineUtils;
Expand Down
2 changes: 1 addition & 1 deletion test/dotnet-watch.Tests/HotReload/ApplyDeltaTests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -73,7 +73,7 @@ public static void Print()
App.AssertOutputContains("dotnet watch 🔥 Hot reload capabilities: AddExplicitInterfaceImplementation AddFieldRva AddInstanceFieldToExistingType AddMethodToExistingType AddStaticFieldToExistingType Baseline ChangeCustomAttributes GenericAddFieldToExistingType GenericAddMethodToExistingType GenericUpdateMethod NewTypeDefinition UpdateParameters.");
}

[Fact]
[Fact(Skip = "https://github.com/dotnet/sdk/issues/52576")]
public async Task ProjectChange_UpdateDirectoryBuildPropsThenUpdateSource()
{
var testAsset = TestAssets.CopyTestAsset("WatchAppWithProjectDeps")
Expand Down