From 63a619e45841b79894af5486954ab6c57d1d2951 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Wed, 4 Feb 2026 19:50:14 +0000 Subject: [PATCH 1/6] Initial plan From 5041b88b6694126c1cecc1935f5ef88e603d412d Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Wed, 4 Feb 2026 19:58:37 +0000 Subject: [PATCH 2/6] Fix dotnet watch run --no-hot-reload suppressing stdout output Co-authored-by: tmat <41759+tmat@users.noreply.github.com> --- .../dotnet-watch/CommandLine/CommandLineOptions.cs | 2 +- src/BuiltInTools/dotnet-watch/Watch/DotNetWatcher.cs | 5 +++-- 2 files changed, 4 insertions(+), 3 deletions(-) diff --git a/src/BuiltInTools/dotnet-watch/CommandLine/CommandLineOptions.cs b/src/BuiltInTools/dotnet-watch/CommandLine/CommandLineOptions.cs index 5a5306fe2ddf..6472fa6b0612 100644 --- a/src/BuiltInTools/dotnet-watch/CommandLine/CommandLineOptions.cs +++ b/src/BuiltInTools/dotnet-watch/CommandLine/CommandLineOptions.cs @@ -195,7 +195,7 @@ private static IReadOnlyList GetCommandArguments( { continue; } - + // forward forwardable option if the subcommand supports it: if (!command.Options.Any(option => option.Name == optionResult.Option.Name)) { diff --git a/src/BuiltInTools/dotnet-watch/Watch/DotNetWatcher.cs b/src/BuiltInTools/dotnet-watch/Watch/DotNetWatcher.cs index b6fb10c29286..881ccbfd5425 100644 --- a/src/BuiltInTools/dotnet-watch/Watch/DotNetWatcher.cs +++ b/src/BuiltInTools/dotnet-watch/Watch/DotNetWatcher.cs @@ -26,7 +26,7 @@ public static async Task WatchAsync(DotNetWatchContext context, CancellationToke ChangedFile? changedFile = null; var buildEvaluator = new BuildEvaluator(context); - for (var iteration = 0;;iteration++) + for (var iteration = 0; ; iteration++) { if (await buildEvaluator.EvaluateAsync(changedFile, shutdownCancellationToken) is not { } evaluationResult) { @@ -59,7 +59,8 @@ public static async Task WatchAsync(DotNetWatchContext context, CancellationToke { [EnvironmentVariables.Names.DotnetWatch] = "1", [EnvironmentVariables.Names.DotnetWatchIteration] = (iteration + 1).ToString(CultureInfo.InvariantCulture), - } + }, + OnOutput = line => context.ProcessOutputReporter.ReportOutput(line) }; var browserRefreshServer = projectRootNode != null && HotReloadAppModel.InferFromProject(context, projectRootNode) is WebApplicationAppModel webAppModel From 472d2c423ea3eb439cc8b70042f46e163b70a476 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Wed, 4 Feb 2026 22:45:41 +0000 Subject: [PATCH 3/6] Add test to verify stdout is captured with --no-hot-reload Co-authored-by: tmat <41759+tmat@users.noreply.github.com> --- .../Aspire/AspireServiceFactoryTests.cs | 2 +- .../Browser/BrowserRefreshServerTests.cs | 2 +- test/dotnet-watch.Tests/Browser/BrowserTests.cs | 2 +- .../Build/FileSetSerializerTests.cs | 2 +- .../CommandLine/CommandLineOptionsTests.cs | 8 ++++---- .../dotnet-watch.Tests/CommandLine/ProgramTests.cs | 6 +++--- .../HotReload/ApplyDeltaTests.cs | 2 +- .../HotReload/HotReloadDotNetWatcherTests.cs | 2 +- .../HotReload/RuntimeProcessLauncherTests.cs | 4 ++-- .../TestUtilities/TestLoggerFactory.cs | 2 +- .../TestUtilities/WatchableApp.cs | 2 +- test/dotnet-watch.Tests/Watch/NoDepsAppTests.cs | 14 ++++++++++++++ 12 files changed, 31 insertions(+), 17 deletions(-) diff --git a/test/dotnet-watch.Tests/Aspire/AspireServiceFactoryTests.cs b/test/dotnet-watch.Tests/Aspire/AspireServiceFactoryTests.cs index 5e5c721e9f0d..c23d976c3e80 100644 --- a/test/dotnet-watch.Tests/Aspire/AspireServiceFactoryTests.cs +++ b/test/dotnet-watch.Tests/Aspire/AspireServiceFactoryTests.cs @@ -38,7 +38,7 @@ public void GetRunCommandArguments_DisableLaunchProfile() var args = AspireServiceFactory.SessionManager.GetRunCommandArguments(request, hostLaunchProfile: "H"); - AssertEx.SequenceEqual(["--project", "a.csproj", "--no-launch-profile" ], args); + AssertEx.SequenceEqual(["--project", "a.csproj", "--no-launch-profile"], args); } [Theory] diff --git a/test/dotnet-watch.Tests/Browser/BrowserRefreshServerTests.cs b/test/dotnet-watch.Tests/Browser/BrowserRefreshServerTests.cs index 236c99ec077d..aba700384106 100644 --- a/test/dotnet-watch.Tests/Browser/BrowserRefreshServerTests.cs +++ b/test/dotnet-watch.Tests/Browser/BrowserRefreshServerTests.cs @@ -17,7 +17,7 @@ public void Dispose() [Theory] [CombinatorialData] - public async Task ConfigureLaunchEnvironmentAsync(LogLevel logLevel, bool enableHotReload) + public async Task ConfigureLaunchEnvironmentAsync(LogLevel logLevel, bool enableHotReload) { var middlewarePath = Path.GetTempPath(); var middlewareFileName = Path.GetFileNameWithoutExtension(middlewarePath); diff --git a/test/dotnet-watch.Tests/Browser/BrowserTests.cs b/test/dotnet-watch.Tests/Browser/BrowserTests.cs index 17e21166bf3f..3f4b40189014 100644 --- a/test/dotnet-watch.Tests/Browser/BrowserTests.cs +++ b/test/dotnet-watch.Tests/Browser/BrowserTests.cs @@ -51,7 +51,7 @@ public async Task BrowserDiagnostics() App.Process.ClearOutput(); var homePagePath = Path.Combine(testAsset.Path, "RazorApp", "Components", "Pages", "Home.razor"); - + // rude edit: UpdateSourceFile(homePagePath, src => src.Replace("/* member placeholder */", """ public virtual int F() => 1; diff --git a/test/dotnet-watch.Tests/Build/FileSetSerializerTests.cs b/test/dotnet-watch.Tests/Build/FileSetSerializerTests.cs index 77bd1b8abe68..b60d062f9cee 100644 --- a/test/dotnet-watch.Tests/Build/FileSetSerializerTests.cs +++ b/test/dotnet-watch.Tests/Build/FileSetSerializerTests.cs @@ -12,7 +12,7 @@ namespace Microsoft.DotNet.Watch.UnitTests; public class FileSetSerializerTests(ITestOutputHelper output) { - private readonly TestAssetsManager _testAssetManager = new (output); + private readonly TestAssetsManager _testAssetManager = new(output); private static string Serialize(MSBuildFileSetResult fileSetResult, Stream stream) { diff --git a/test/dotnet-watch.Tests/CommandLine/CommandLineOptionsTests.cs b/test/dotnet-watch.Tests/CommandLine/CommandLineOptionsTests.cs index c4c2c1796031..ef328a883e17 100644 --- a/test/dotnet-watch.Tests/CommandLine/CommandLineOptionsTests.cs +++ b/test/dotnet-watch.Tests/CommandLine/CommandLineOptionsTests.cs @@ -377,12 +377,12 @@ public void OptionDuplicates_NotAllowed(string option) [Theory] [InlineData(new[] { "--unrecognized-arg" }, new[] { "--unrecognized-arg" })] [InlineData(new[] { "run" }, new string[] { })] - [InlineData(new[] { "run", "--", "runarg" }, new[] { "--", "runarg" })] - [InlineData(new[] { "--verbose", "run", "runarg1", "-runarg2" }, new[] { "runarg1", "-runarg2" })] + [InlineData(new[] { "run", "--", "runarg" }, new[] { "--", "runarg" })] + [InlineData(new[] { "--verbose", "run", "runarg1", "-runarg2" }, new[] { "runarg1", "-runarg2" })] // run is after -- and therefore not parsed as a command: - [InlineData(new[] { "--verbose", "--", "run", "--", "runarg" }, new[] { "--", "run", "--", "runarg" })] + [InlineData(new[] { "--verbose", "--", "run", "--", "runarg" }, new[] { "--", "run", "--", "runarg" })] // run is before -- and therefore parsed as a command: - [InlineData(new[] { "--verbose", "run", "--", "--", "runarg" }, new[] { "--", "--", "runarg" })] + [InlineData(new[] { "--verbose", "run", "--", "--", "runarg" }, new[] { "--", "--", "runarg" })] public void ParsesRemainingArgs(string[] args, string[] expected) { var options = VerifyOptions(args); diff --git a/test/dotnet-watch.Tests/CommandLine/ProgramTests.cs b/test/dotnet-watch.Tests/CommandLine/ProgramTests.cs index 30c1e117f48a..5048761285e1 100644 --- a/test/dotnet-watch.Tests/CommandLine/ProgramTests.cs +++ b/test/dotnet-watch.Tests/CommandLine/ProgramTests.cs @@ -72,7 +72,7 @@ public async Task Arguments(string[] arguments, string expectedApplicationArgs) [InlineData(new[] { "--no-hot-reload", "--", "run", "args" }, "Argument Specified in Props,run,args")] [InlineData(new[] { "--", "run", "args" }, "Argument Specified in Props,run,args")] // if arguments specified on command line the ones from launch profile are ignored - [InlineData(new[] { "-lp", "P1", "--", "run", "args" },"Argument Specified in Props,run,args")] + [InlineData(new[] { "-lp", "P1", "--", "run", "args" }, "Argument Specified in Props,run,args")] // arguments specified in build file override arguments in launch profile [InlineData(new[] { "-lp", "P1" }, "Argument Specified in Props")] public async Task Arguments_HostArguments(string[] arguments, string expectedApplicationArgs) @@ -105,7 +105,7 @@ public async Task RunArguments_NoHotReload() "-v", "minimal", "--", // the following args are application args - "-v", + "-v", ]); Assert.Equal("-v", await App.AssertOutputLineStartsWith("Arguments = ")); @@ -296,7 +296,7 @@ public async Task PublishCommand() // evaluation affected by -c option: Assert.Contains("-property:Configuration=Release", App.Process.Output.Single(line => line.Contains("/t:GenerateWatchList"))); - + App.AssertOutputContains("dotnet watch ⌚ Command 'publish' does not support Hot Reload."); App.AssertOutputContains(Path.Combine("Release", ToolsetInfo.CurrentTargetFramework, "publish")); diff --git a/test/dotnet-watch.Tests/HotReload/ApplyDeltaTests.cs b/test/dotnet-watch.Tests/HotReload/ApplyDeltaTests.cs index 057fe69e3e78..047f5e71c01b 100644 --- a/test/dotnet-watch.Tests/HotReload/ApplyDeltaTests.cs +++ b/test/dotnet-watch.Tests/HotReload/ApplyDeltaTests.cs @@ -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(Skip="https://github.com/dotnet/sdk/issues/52680")] + [Fact(Skip = "https://github.com/dotnet/sdk/issues/52680")] public async Task ProjectChange_UpdateDirectoryBuildPropsThenUpdateSource() { var testAsset = TestAssets.CopyTestAsset("WatchAppWithProjectDeps") diff --git a/test/dotnet-watch.Tests/HotReload/HotReloadDotNetWatcherTests.cs b/test/dotnet-watch.Tests/HotReload/HotReloadDotNetWatcherTests.cs index ac47a4ef9943..b479cbdc13f5 100644 --- a/test/dotnet-watch.Tests/HotReload/HotReloadDotNetWatcherTests.cs +++ b/test/dotnet-watch.Tests/HotReload/HotReloadDotNetWatcherTests.cs @@ -14,7 +14,7 @@ public class HotReloadDotNetWatcherTests [InlineData(new[] { ChangeKind.Update, ChangeKind.Delete }, new[] { ChangeKind.Delete })] [InlineData(new[] { ChangeKind.Add, ChangeKind.Update }, new[] { ChangeKind.Add })] [InlineData(new[] { ChangeKind.Add, ChangeKind.Delete }, new ChangeKind[] { })] - [InlineData(new[] { ChangeKind.Delete, ChangeKind.Add}, new[] { ChangeKind.Update })] + [InlineData(new[] { ChangeKind.Delete, ChangeKind.Add }, new[] { ChangeKind.Update })] [InlineData(new[] { ChangeKind.Add, ChangeKind.Add }, new[] { ChangeKind.Add })] [InlineData(new[] { ChangeKind.Delete, ChangeKind.Delete }, new[] { ChangeKind.Delete })] diff --git a/test/dotnet-watch.Tests/HotReload/RuntimeProcessLauncherTests.cs b/test/dotnet-watch.Tests/HotReload/RuntimeProcessLauncherTests.cs index 81130fbc2092..73df59b26698 100644 --- a/test/dotnet-watch.Tests/HotReload/RuntimeProcessLauncherTests.cs +++ b/test/dotnet-watch.Tests/HotReload/RuntimeProcessLauncherTests.cs @@ -102,7 +102,7 @@ private RunningWatcher StartWatcher(TestAsset testAsset, string[] args, string? var processRunner = new ProcessRunner(environmentOptions.GetProcessCleanupTimeout(isHotReloadEnabled: true)); var program = Program.TryCreate( - TestOptions.GetCommandLineOptions(["--verbose", ..args]), + TestOptions.GetCommandLineOptions(["--verbose", .. args]), console, environmentOptions, loggerFactory, @@ -610,7 +610,7 @@ public async Task IgnoredChange(bool isExisting, bool isIncluded, DirectoryKind Log("Waiting for changes..."); await waitingForChanges.WaitAsync(w.ShutdownSource.Token); - + UpdateSourceFile(path, "class C { int F() => 2; }"); switch ((isExisting, isIncluded, directoryKind)) diff --git a/test/dotnet-watch.Tests/TestUtilities/TestLoggerFactory.cs b/test/dotnet-watch.Tests/TestUtilities/TestLoggerFactory.cs index be1e69682952..3a0b50b5f717 100644 --- a/test/dotnet-watch.Tests/TestUtilities/TestLoggerFactory.cs +++ b/test/dotnet-watch.Tests/TestUtilities/TestLoggerFactory.cs @@ -12,6 +12,6 @@ internal class TestLoggerFactory(ITestOutputHelper? output = null) : ILoggerFact public ILogger CreateLogger(string categoryName) => CreateLoggerImpl?.Invoke(categoryName) ?? new TestLogger(output); - public void AddProvider(ILoggerProvider provider) {} + public void AddProvider(ILoggerProvider provider) { } public void Dispose() { } } diff --git a/test/dotnet-watch.Tests/TestUtilities/WatchableApp.cs b/test/dotnet-watch.Tests/TestUtilities/WatchableApp.cs index 7ef1230edb39..bf6df2cbec6c 100644 --- a/test/dotnet-watch.Tests/TestUtilities/WatchableApp.cs +++ b/test/dotnet-watch.Tests/TestUtilities/WatchableApp.cs @@ -65,7 +65,7 @@ public async ValueTask WaitUntilOutputContains(string text, [CallerFilePath] str { Logger.Log($"Test found output: '{text}'", testPath, testLine); } - else + else { Logger.Log($"Test waiting for output: '{text}'", testPath, testLine); _ = await WaitForOutputLineMatching(line => line.Contains(text)); diff --git a/test/dotnet-watch.Tests/Watch/NoDepsAppTests.cs b/test/dotnet-watch.Tests/Watch/NoDepsAppTests.cs index fe93ef940c90..7cbe19cefae0 100644 --- a/test/dotnet-watch.Tests/Watch/NoDepsAppTests.cs +++ b/test/dotnet-watch.Tests/Watch/NoDepsAppTests.cs @@ -48,5 +48,19 @@ public async Task RestartProcessThatTerminatesAfterFileChange() Assert.NotEqual(processIdentifier, processIdentifier2); await App.AssertExiting(); // process should exit after run } + + [Fact] + public async Task CapturesStdOutWithNoHotReload() + { + var testAsset = TestAssets.CopyTestAsset(AppName) + .WithSource(); + + App.Start(testAsset, ["--no-hot-reload"]); + + // Verify that stdout from the application is captured + await App.AssertOutputLineStartsWith("Started"); + await App.AssertOutputLineStartsWith("Process identifier ="); + await App.AssertExiting(); + } } } From 1d5da176143cfc1712bf006f3505c5e6799a566c Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Thu, 5 Feb 2026 22:24:25 +0000 Subject: [PATCH 4/6] Revert formatting changes Co-authored-by: tmat <41759+tmat@users.noreply.github.com> --- .../dotnet-watch/CommandLine/CommandLineOptions.cs | 2 +- src/BuiltInTools/dotnet-watch/Watch/DotNetWatcher.cs | 2 +- .../Aspire/AspireServiceFactoryTests.cs | 2 +- .../Browser/BrowserRefreshServerTests.cs | 2 +- test/dotnet-watch.Tests/Browser/BrowserTests.cs | 2 +- test/dotnet-watch.Tests/Build/FileSetSerializerTests.cs | 2 +- .../CommandLine/CommandLineOptionsTests.cs | 8 ++++---- test/dotnet-watch.Tests/CommandLine/ProgramTests.cs | 6 +++--- test/dotnet-watch.Tests/HotReload/ApplyDeltaTests.cs | 2 +- .../HotReload/HotReloadDotNetWatcherTests.cs | 2 +- .../HotReload/RuntimeProcessLauncherTests.cs | 4 ++-- .../dotnet-watch.Tests/TestUtilities/TestLoggerFactory.cs | 2 +- test/dotnet-watch.Tests/TestUtilities/WatchableApp.cs | 2 +- 13 files changed, 19 insertions(+), 19 deletions(-) diff --git a/src/BuiltInTools/dotnet-watch/CommandLine/CommandLineOptions.cs b/src/BuiltInTools/dotnet-watch/CommandLine/CommandLineOptions.cs index 6472fa6b0612..5a5306fe2ddf 100644 --- a/src/BuiltInTools/dotnet-watch/CommandLine/CommandLineOptions.cs +++ b/src/BuiltInTools/dotnet-watch/CommandLine/CommandLineOptions.cs @@ -195,7 +195,7 @@ private static IReadOnlyList GetCommandArguments( { continue; } - + // forward forwardable option if the subcommand supports it: if (!command.Options.Any(option => option.Name == optionResult.Option.Name)) { diff --git a/src/BuiltInTools/dotnet-watch/Watch/DotNetWatcher.cs b/src/BuiltInTools/dotnet-watch/Watch/DotNetWatcher.cs index 881ccbfd5425..47909070034c 100644 --- a/src/BuiltInTools/dotnet-watch/Watch/DotNetWatcher.cs +++ b/src/BuiltInTools/dotnet-watch/Watch/DotNetWatcher.cs @@ -26,7 +26,7 @@ public static async Task WatchAsync(DotNetWatchContext context, CancellationToke ChangedFile? changedFile = null; var buildEvaluator = new BuildEvaluator(context); - for (var iteration = 0; ; iteration++) + for (var iteration = 0;;iteration++) { if (await buildEvaluator.EvaluateAsync(changedFile, shutdownCancellationToken) is not { } evaluationResult) { diff --git a/test/dotnet-watch.Tests/Aspire/AspireServiceFactoryTests.cs b/test/dotnet-watch.Tests/Aspire/AspireServiceFactoryTests.cs index c23d976c3e80..5e5c721e9f0d 100644 --- a/test/dotnet-watch.Tests/Aspire/AspireServiceFactoryTests.cs +++ b/test/dotnet-watch.Tests/Aspire/AspireServiceFactoryTests.cs @@ -38,7 +38,7 @@ public void GetRunCommandArguments_DisableLaunchProfile() var args = AspireServiceFactory.SessionManager.GetRunCommandArguments(request, hostLaunchProfile: "H"); - AssertEx.SequenceEqual(["--project", "a.csproj", "--no-launch-profile"], args); + AssertEx.SequenceEqual(["--project", "a.csproj", "--no-launch-profile" ], args); } [Theory] diff --git a/test/dotnet-watch.Tests/Browser/BrowserRefreshServerTests.cs b/test/dotnet-watch.Tests/Browser/BrowserRefreshServerTests.cs index aba700384106..236c99ec077d 100644 --- a/test/dotnet-watch.Tests/Browser/BrowserRefreshServerTests.cs +++ b/test/dotnet-watch.Tests/Browser/BrowserRefreshServerTests.cs @@ -17,7 +17,7 @@ public void Dispose() [Theory] [CombinatorialData] - public async Task ConfigureLaunchEnvironmentAsync(LogLevel logLevel, bool enableHotReload) + public async Task ConfigureLaunchEnvironmentAsync(LogLevel logLevel, bool enableHotReload) { var middlewarePath = Path.GetTempPath(); var middlewareFileName = Path.GetFileNameWithoutExtension(middlewarePath); diff --git a/test/dotnet-watch.Tests/Browser/BrowserTests.cs b/test/dotnet-watch.Tests/Browser/BrowserTests.cs index 3f4b40189014..17e21166bf3f 100644 --- a/test/dotnet-watch.Tests/Browser/BrowserTests.cs +++ b/test/dotnet-watch.Tests/Browser/BrowserTests.cs @@ -51,7 +51,7 @@ public async Task BrowserDiagnostics() App.Process.ClearOutput(); var homePagePath = Path.Combine(testAsset.Path, "RazorApp", "Components", "Pages", "Home.razor"); - + // rude edit: UpdateSourceFile(homePagePath, src => src.Replace("/* member placeholder */", """ public virtual int F() => 1; diff --git a/test/dotnet-watch.Tests/Build/FileSetSerializerTests.cs b/test/dotnet-watch.Tests/Build/FileSetSerializerTests.cs index b60d062f9cee..77bd1b8abe68 100644 --- a/test/dotnet-watch.Tests/Build/FileSetSerializerTests.cs +++ b/test/dotnet-watch.Tests/Build/FileSetSerializerTests.cs @@ -12,7 +12,7 @@ namespace Microsoft.DotNet.Watch.UnitTests; public class FileSetSerializerTests(ITestOutputHelper output) { - private readonly TestAssetsManager _testAssetManager = new(output); + private readonly TestAssetsManager _testAssetManager = new (output); private static string Serialize(MSBuildFileSetResult fileSetResult, Stream stream) { diff --git a/test/dotnet-watch.Tests/CommandLine/CommandLineOptionsTests.cs b/test/dotnet-watch.Tests/CommandLine/CommandLineOptionsTests.cs index ef328a883e17..c4c2c1796031 100644 --- a/test/dotnet-watch.Tests/CommandLine/CommandLineOptionsTests.cs +++ b/test/dotnet-watch.Tests/CommandLine/CommandLineOptionsTests.cs @@ -377,12 +377,12 @@ public void OptionDuplicates_NotAllowed(string option) [Theory] [InlineData(new[] { "--unrecognized-arg" }, new[] { "--unrecognized-arg" })] [InlineData(new[] { "run" }, new string[] { })] - [InlineData(new[] { "run", "--", "runarg" }, new[] { "--", "runarg" })] - [InlineData(new[] { "--verbose", "run", "runarg1", "-runarg2" }, new[] { "runarg1", "-runarg2" })] + [InlineData(new[] { "run", "--", "runarg" }, new[] { "--", "runarg" })] + [InlineData(new[] { "--verbose", "run", "runarg1", "-runarg2" }, new[] { "runarg1", "-runarg2" })] // run is after -- and therefore not parsed as a command: - [InlineData(new[] { "--verbose", "--", "run", "--", "runarg" }, new[] { "--", "run", "--", "runarg" })] + [InlineData(new[] { "--verbose", "--", "run", "--", "runarg" }, new[] { "--", "run", "--", "runarg" })] // run is before -- and therefore parsed as a command: - [InlineData(new[] { "--verbose", "run", "--", "--", "runarg" }, new[] { "--", "--", "runarg" })] + [InlineData(new[] { "--verbose", "run", "--", "--", "runarg" }, new[] { "--", "--", "runarg" })] public void ParsesRemainingArgs(string[] args, string[] expected) { var options = VerifyOptions(args); diff --git a/test/dotnet-watch.Tests/CommandLine/ProgramTests.cs b/test/dotnet-watch.Tests/CommandLine/ProgramTests.cs index 5048761285e1..30c1e117f48a 100644 --- a/test/dotnet-watch.Tests/CommandLine/ProgramTests.cs +++ b/test/dotnet-watch.Tests/CommandLine/ProgramTests.cs @@ -72,7 +72,7 @@ public async Task Arguments(string[] arguments, string expectedApplicationArgs) [InlineData(new[] { "--no-hot-reload", "--", "run", "args" }, "Argument Specified in Props,run,args")] [InlineData(new[] { "--", "run", "args" }, "Argument Specified in Props,run,args")] // if arguments specified on command line the ones from launch profile are ignored - [InlineData(new[] { "-lp", "P1", "--", "run", "args" }, "Argument Specified in Props,run,args")] + [InlineData(new[] { "-lp", "P1", "--", "run", "args" },"Argument Specified in Props,run,args")] // arguments specified in build file override arguments in launch profile [InlineData(new[] { "-lp", "P1" }, "Argument Specified in Props")] public async Task Arguments_HostArguments(string[] arguments, string expectedApplicationArgs) @@ -105,7 +105,7 @@ public async Task RunArguments_NoHotReload() "-v", "minimal", "--", // the following args are application args - "-v", + "-v", ]); Assert.Equal("-v", await App.AssertOutputLineStartsWith("Arguments = ")); @@ -296,7 +296,7 @@ public async Task PublishCommand() // evaluation affected by -c option: Assert.Contains("-property:Configuration=Release", App.Process.Output.Single(line => line.Contains("/t:GenerateWatchList"))); - + App.AssertOutputContains("dotnet watch ⌚ Command 'publish' does not support Hot Reload."); App.AssertOutputContains(Path.Combine("Release", ToolsetInfo.CurrentTargetFramework, "publish")); diff --git a/test/dotnet-watch.Tests/HotReload/ApplyDeltaTests.cs b/test/dotnet-watch.Tests/HotReload/ApplyDeltaTests.cs index 047f5e71c01b..057fe69e3e78 100644 --- a/test/dotnet-watch.Tests/HotReload/ApplyDeltaTests.cs +++ b/test/dotnet-watch.Tests/HotReload/ApplyDeltaTests.cs @@ -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(Skip = "https://github.com/dotnet/sdk/issues/52680")] + [Fact(Skip="https://github.com/dotnet/sdk/issues/52680")] public async Task ProjectChange_UpdateDirectoryBuildPropsThenUpdateSource() { var testAsset = TestAssets.CopyTestAsset("WatchAppWithProjectDeps") diff --git a/test/dotnet-watch.Tests/HotReload/HotReloadDotNetWatcherTests.cs b/test/dotnet-watch.Tests/HotReload/HotReloadDotNetWatcherTests.cs index b479cbdc13f5..ac47a4ef9943 100644 --- a/test/dotnet-watch.Tests/HotReload/HotReloadDotNetWatcherTests.cs +++ b/test/dotnet-watch.Tests/HotReload/HotReloadDotNetWatcherTests.cs @@ -14,7 +14,7 @@ public class HotReloadDotNetWatcherTests [InlineData(new[] { ChangeKind.Update, ChangeKind.Delete }, new[] { ChangeKind.Delete })] [InlineData(new[] { ChangeKind.Add, ChangeKind.Update }, new[] { ChangeKind.Add })] [InlineData(new[] { ChangeKind.Add, ChangeKind.Delete }, new ChangeKind[] { })] - [InlineData(new[] { ChangeKind.Delete, ChangeKind.Add }, new[] { ChangeKind.Update })] + [InlineData(new[] { ChangeKind.Delete, ChangeKind.Add}, new[] { ChangeKind.Update })] [InlineData(new[] { ChangeKind.Add, ChangeKind.Add }, new[] { ChangeKind.Add })] [InlineData(new[] { ChangeKind.Delete, ChangeKind.Delete }, new[] { ChangeKind.Delete })] diff --git a/test/dotnet-watch.Tests/HotReload/RuntimeProcessLauncherTests.cs b/test/dotnet-watch.Tests/HotReload/RuntimeProcessLauncherTests.cs index 73df59b26698..81130fbc2092 100644 --- a/test/dotnet-watch.Tests/HotReload/RuntimeProcessLauncherTests.cs +++ b/test/dotnet-watch.Tests/HotReload/RuntimeProcessLauncherTests.cs @@ -102,7 +102,7 @@ private RunningWatcher StartWatcher(TestAsset testAsset, string[] args, string? var processRunner = new ProcessRunner(environmentOptions.GetProcessCleanupTimeout(isHotReloadEnabled: true)); var program = Program.TryCreate( - TestOptions.GetCommandLineOptions(["--verbose", .. args]), + TestOptions.GetCommandLineOptions(["--verbose", ..args]), console, environmentOptions, loggerFactory, @@ -610,7 +610,7 @@ public async Task IgnoredChange(bool isExisting, bool isIncluded, DirectoryKind Log("Waiting for changes..."); await waitingForChanges.WaitAsync(w.ShutdownSource.Token); - + UpdateSourceFile(path, "class C { int F() => 2; }"); switch ((isExisting, isIncluded, directoryKind)) diff --git a/test/dotnet-watch.Tests/TestUtilities/TestLoggerFactory.cs b/test/dotnet-watch.Tests/TestUtilities/TestLoggerFactory.cs index 3a0b50b5f717..be1e69682952 100644 --- a/test/dotnet-watch.Tests/TestUtilities/TestLoggerFactory.cs +++ b/test/dotnet-watch.Tests/TestUtilities/TestLoggerFactory.cs @@ -12,6 +12,6 @@ internal class TestLoggerFactory(ITestOutputHelper? output = null) : ILoggerFact public ILogger CreateLogger(string categoryName) => CreateLoggerImpl?.Invoke(categoryName) ?? new TestLogger(output); - public void AddProvider(ILoggerProvider provider) { } + public void AddProvider(ILoggerProvider provider) {} public void Dispose() { } } diff --git a/test/dotnet-watch.Tests/TestUtilities/WatchableApp.cs b/test/dotnet-watch.Tests/TestUtilities/WatchableApp.cs index bf6df2cbec6c..7ef1230edb39 100644 --- a/test/dotnet-watch.Tests/TestUtilities/WatchableApp.cs +++ b/test/dotnet-watch.Tests/TestUtilities/WatchableApp.cs @@ -65,7 +65,7 @@ public async ValueTask WaitUntilOutputContains(string text, [CallerFilePath] str { Logger.Log($"Test found output: '{text}'", testPath, testLine); } - else + else { Logger.Log($"Test waiting for output: '{text}'", testPath, testLine); _ = await WaitForOutputLineMatching(line => line.Contains(text)); From 9a927a082fe670f6b4f59e7f97491a1cc3c0bfb4 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Thu, 5 Feb 2026 22:48:52 +0000 Subject: [PATCH 5/6] Remove redundant test and unskip existing tests that verify stdout Co-authored-by: tmat <41759+tmat@users.noreply.github.com> --- .../dotnet-watch.Tests/Watch/NoDepsAppTests.cs | 18 ++---------------- 1 file changed, 2 insertions(+), 16 deletions(-) diff --git a/test/dotnet-watch.Tests/Watch/NoDepsAppTests.cs b/test/dotnet-watch.Tests/Watch/NoDepsAppTests.cs index 7cbe19cefae0..836170ec871d 100644 --- a/test/dotnet-watch.Tests/Watch/NoDepsAppTests.cs +++ b/test/dotnet-watch.Tests/Watch/NoDepsAppTests.cs @@ -7,7 +7,7 @@ public class NoDepsAppTests(ITestOutputHelper logger) : DotNetWatchTestBase(logg { private const string AppName = "WatchNoDepsApp"; - [Fact(Skip = "https://github.com/dotnet/sdk/issues/42921")] + [Fact] public async Task RestartProcessOnFileChange() { var testAsset = TestAssets.CopyTestAsset(AppName) @@ -25,7 +25,7 @@ public async Task RestartProcessOnFileChange() Assert.NotEqual(processIdentifier, processIdentifier2); } - [Fact(Skip = "https://github.com/dotnet/sdk/issues/42921")] + [Fact] public async Task RestartProcessThatTerminatesAfterFileChange() { var testAsset = TestAssets.CopyTestAsset(AppName) @@ -48,19 +48,5 @@ public async Task RestartProcessThatTerminatesAfterFileChange() Assert.NotEqual(processIdentifier, processIdentifier2); await App.AssertExiting(); // process should exit after run } - - [Fact] - public async Task CapturesStdOutWithNoHotReload() - { - var testAsset = TestAssets.CopyTestAsset(AppName) - .WithSource(); - - App.Start(testAsset, ["--no-hot-reload"]); - - // Verify that stdout from the application is captured - await App.AssertOutputLineStartsWith("Started"); - await App.AssertOutputLineStartsWith("Process identifier ="); - await App.AssertExiting(); - } } } From ec1899c0312bce31db6e5e345e3b1409678c9f37 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Fri, 6 Feb 2026 04:32:18 +0000 Subject: [PATCH 6/6] Re-skip flaky tests and add simple test for stdout capture Co-authored-by: tmat <41759+tmat@users.noreply.github.com> --- .../dotnet-watch.Tests/Watch/NoDepsAppTests.cs | 18 ++++++++++++++++-- 1 file changed, 16 insertions(+), 2 deletions(-) diff --git a/test/dotnet-watch.Tests/Watch/NoDepsAppTests.cs b/test/dotnet-watch.Tests/Watch/NoDepsAppTests.cs index 836170ec871d..98d865d207ca 100644 --- a/test/dotnet-watch.Tests/Watch/NoDepsAppTests.cs +++ b/test/dotnet-watch.Tests/Watch/NoDepsAppTests.cs @@ -7,7 +7,7 @@ public class NoDepsAppTests(ITestOutputHelper logger) : DotNetWatchTestBase(logg { private const string AppName = "WatchNoDepsApp"; - [Fact] + [Fact(Skip = "https://github.com/dotnet/sdk/issues/42921")] public async Task RestartProcessOnFileChange() { var testAsset = TestAssets.CopyTestAsset(AppName) @@ -25,7 +25,7 @@ public async Task RestartProcessOnFileChange() Assert.NotEqual(processIdentifier, processIdentifier2); } - [Fact] + [Fact(Skip = "https://github.com/dotnet/sdk/issues/42921")] public async Task RestartProcessThatTerminatesAfterFileChange() { var testAsset = TestAssets.CopyTestAsset(AppName) @@ -48,5 +48,19 @@ public async Task RestartProcessThatTerminatesAfterFileChange() Assert.NotEqual(processIdentifier, processIdentifier2); await App.AssertExiting(); // process should exit after run } + + [Fact] + public async Task CapturesStdOutWithNoHotReload() + { + var testAsset = TestAssets.CopyTestAsset(AppName) + .WithSource(); + + App.Start(testAsset, ["--no-hot-reload"]); + + // Verify stdout is captured - application prints "Started" and "Process identifier" + await App.AssertOutputLineStartsWith("Started"); + await App.AssertOutputLineStartsWith("Process identifier ="); + await App.AssertExiting(); + } } }