Conversation
c0503a9 to
7e292e1
Compare
|
@DustinCampbell ptal |
… from TestReporter to a separate type.
There was a problem hiding this comment.
Pull request overview
This PR refactors dotnet watch’s test infrastructure to enable high-parallel test execution with improved diagnostics/robustness, and extends the Watch.Aspire CLI/tooling to support Aspire’s polyglot watch scenarios via host, server, and resource commands (named-pipe based coordination + status/control channels).
Changes:
- Reworks watch test utilities (process/output/event observation) and redistributes tests to run safely in parallel.
- Introduces/expands Aspire watch CLI launchers and server/resource orchestration, including status/control pipe messaging.
- Updates watch logging/environment plumbing (log prefixes, muxer path derivation from SDK directory, notification-only log events).
Reviewed changes
Copilot reviewed 92 out of 93 changed files in this pull request and generated 7 comments.
Show a summary per file
| File | Description |
|---|---|
| test/dotnet-watch.Tests/Watch/NoDepsAppTests.cs | Removed; tests moved/rewritten under new file-update suite. |
| test/dotnet-watch.Tests/Watch/GlobbingAppTests.cs | Adjusts output assertions to new process/output utilities. |
| test/dotnet-watch.Tests/Watch/FileUpdateTests.cs | New file-change restart coverage using updated output waiting APIs. |
| test/dotnet-watch.Tests/TestUtilities/TestRuntimeProcessLauncher.cs | Adds Launch helper to align with in-proc watcher and restart semantics. |
| test/dotnet-watch.Tests/TestUtilities/TestReporter.cs | Simplifies reporter behavior; shifts event observation out of reporter. |
| test/dotnet-watch.Tests/TestUtilities/TestOptions.cs | Environment options now derive SDK dir and log prefix; removes muxerPath param. |
| test/dotnet-watch.Tests/TestUtilities/TestObservableLoggerFactory.cs | New: observes EventIds during logging for deterministic test signaling. |
| test/dotnet-watch.Tests/TestUtilities/TestEventObserver.cs | New: event-to-action registry for semaphores/actions. |
| test/dotnet-watch.Tests/TestUtilities/MockFileSetFactory.cs | Updates environment options call-site. |
| test/dotnet-watch.Tests/TestUtilities/InProcTestWatcher.cs | New: shared in-proc watcher harness for tests. |
| test/dotnet-watch.Tests/TestUtilities/InProcBuildTestCollection.cs | Removed; replaced by explicit build semaphore usage. |
| test/dotnet-watch.Tests/TestUtilities/DotNetWatchTestBase.cs | Base test now uses WatchableApp factory + adds in-proc watcher creation. |
| test/dotnet-watch.Tests/HotReload/SourceFileUpdateTests.cs | Removes scenarios moved into a dedicated file. |
| test/dotnet-watch.Tests/HotReload/SourceFileUpdateTests.HotReloadNotSupported.cs | New split-out suite for “hot reload not supported” scenarios. |
| test/dotnet-watch.Tests/HotReload/RuntimeProcessLauncherTests.cs | Refactored to use shared in-proc watcher + observer-based signaling. |
| test/dotnet-watch.Tests/HotReload/ProjectUpdateInProcTests.cs | New in-proc coverage for project+source updates. |
| test/dotnet-watch.Tests/HotReload/FileExclusionTests.cs | New in-proc coverage for file exclusion/ignored changes. |
| test/dotnet-watch.Tests/HotReload/CtrlRTests.cs | New in-proc coverage for Ctrl+R behaviors. |
| test/dotnet-watch.Tests/HotReload/CompilationHandlerTests.cs | Updates environment options call-site. |
| test/dotnet-watch.Tests/HotReload/AspireHotReloadTests.cs | Adjusts build-message assertions and shutdown expectations. |
| test/dotnet-watch.Tests/ConsoleReporterTests.cs | Updates ConsoleReporter ctor to accept explicit log prefix. |
| test/dotnet-watch.Tests/CommandLine/SubcommandTests.cs | New tests for subcommand behaviors (test/build/msbuild/pack/publish/format). |
| test/dotnet-watch.Tests/CommandLine/ProgramTests.cs | Uses observable logger factory + updated output completion waiting. |
| test/dotnet-watch.Tests/CommandLine/ProgramTests.HostArguments.cs | New split-out suite for host-argument parsing cases. |
| test/dotnet-watch.Tests/CommandLine/ProgramTests.Arguments.cs | New split-out suite for argument forwarding/launch settings cases. |
| test/dotnet-watch.Tests/CommandLine/LaunchSettingsTests.cs | Updates arg plumbing (WatchArgs) and output wait API. |
| test/dotnet-watch.Tests/CommandLine/BinaryLoggerTests.cs | Uses build semaphore to avoid in-proc MSBuild concurrency issues. |
| test/dotnet-watch.Tests/Build/EvaluationTests.cs | Updates env options + improves test asset identifier uniqueness. |
| test/dotnet-new.IntegrationTests/TemplateEngineSamplesTest.cs | Env var dictionary now allows nullable values to match framework changes. |
| test/dotnet-new.IntegrationTests/DotnetClassTemplateTests.cs | Same nullable env var dictionary update. |
| test/dotnet-new.IntegrationTests/CommonTemplatesTests.cs | Same nullable env var dictionary update. |
| test/Microsoft.NET.TestFramework/ToolsetInfo.cs | AddTestEnvironmentVariables now accepts nullable values. |
| test/Microsoft.NET.TestFramework/TestContext.cs | AddTestEnvironmentVariables now accepts nullable values. |
| test/Microsoft.NET.TestFramework/Commands/SdkCommandSpec.cs | Environment dictionary now stores nullable values. |
| test/Microsoft.DotNet.HotReload.Watch.Aspire.Tests/Utilities/PipeUtilities.cs | New helper to read JSONL status events from a named pipe. |
| test/Microsoft.DotNet.HotReload.Watch.Aspire.Tests/Microsoft.DotNet.HotReload.Watch.Aspire.Tests.csproj | Adds Moq dependency. |
| test/Microsoft.DotNet.HotReload.Watch.Aspire.Tests/DotNetWatchOptionsTests.cs | Removed; superseded by new Aspire launcher CLI parsing tests. |
| test/Microsoft.DotNet.HotReload.Watch.Aspire.Tests/DotNetWatchLauncherTests.cs | Removed; replaced by new integration-style launcher tests. |
| test/Microsoft.DotNet.HotReload.Watch.Aspire.Tests/AspireServerLauncherCliTests.cs | New: server CLI parsing tests. |
| test/Microsoft.DotNet.HotReload.Watch.Aspire.Tests/AspireResourceLauncherCliTests.cs | New: resource CLI parsing tests (env vars, launch profile, args). |
| test/Microsoft.DotNet.HotReload.Watch.Aspire.Tests/AspireLauncherTests.cs | New: end-to-end host/server/resource orchestration tests. |
| test/Microsoft.DotNet.HotReload.Watch.Aspire.Tests/AspireHostLauncherTests.cs | New: host launcher option construction tests. |
| test/Microsoft.DotNet.HotReload.Watch.Aspire.Tests/AspireHostLauncherCliTests.cs | New: host CLI parsing tests. |
| test/Microsoft.DotNet.HotReload.Test.Utilities/WatchableApp.cs | Refactors process launch + output waiting; moves to async disposal. |
| test/Microsoft.DotNet.HotReload.Test.Utilities/WatchSdkTest.cs | New shared base for SDK-backed watch tests. |
| test/Microsoft.DotNet.HotReload.Test.Utilities/TestLogger.cs | Ignores LogLevel.None to support notification-only events. |
| test/Microsoft.DotNet.HotReload.Test.Utilities/DebugTestOutputLogger.cs | Makes output robust against disposed test output helper. |
| test/Microsoft.DotNet.HotReload.Test.Utilities/AwaitableProcess.cs | Refactors output capture to Channels + async disposal. |
| src/Microsoft.CodeAnalysis.NetAnalyzers/src/Microsoft.CodeAnalysis.NetAnalyzers.sarif | Formatting/EOF adjustment. |
| src/Dotnet.Watch/dotnet-watch/dotnet-watch.csproj | Simplifies published input file list for testhost publishing. |
| src/Dotnet.Watch/dotnet-watch/Watch/MsBuildFileSetFactory.cs | Uses EnvironmentOptions.GetMuxerPath(). |
| src/Dotnet.Watch/dotnet-watch/Watch/DotNetWatcher.cs | Uses EnvironmentOptions.GetMuxerPath(). |
| src/Dotnet.Watch/dotnet-watch/Program.cs | Centralizes log prefix + SDK-based env options; logger factory signature generalized. |
| src/Dotnet.Watch/Watch/UI/IReporter.cs | Adds configurable log prefix and notification-only message descriptors. |
| src/Dotnet.Watch/Watch/UI/ConsoleReporter.cs | Accepts configurable log prefix. |
| src/Dotnet.Watch/Watch/Process/RunningProject.cs | Moves restart behavior into RestartAsync() and adds restart logging. |
| src/Dotnet.Watch/Watch/Process/ProjectLauncher.cs | Exposes CompilationHandler; uses log prefix for client logger env var. |
| src/Dotnet.Watch/Watch/Microsoft.DotNet.HotReload.Watch.csproj | Switches ProjectTools reference to configurable path + conditional package ref. |
| src/Dotnet.Watch/Watch/HotReload/HotReloadDotNetWatcher.cs | Adds build notifications; refactors multi-project build and logs. |
| src/Dotnet.Watch/Watch/HotReload/CompilationHandler.cs | OS-specific path comparer; adds status notifications; adds restart helper. |
| src/Dotnet.Watch/Watch/Context/EnvironmentVariables.cs | Clarifies ms-based timeout parsing + adds seconds parsing helper. |
| src/Dotnet.Watch/Watch/Context/EnvironmentOptions.cs | Switches from muxer path to SDK directory + GetMuxerPath(). |
| src/Dotnet.Watch/Watch/Build/ProjectRepresentation.cs | Adds IsProjectFile + OS-specific equality/hash semantics. |
| src/Dotnet.Watch/Watch/Build/ProjectBuildManager.cs | Exposes build semaphore for tests. |
| src/Dotnet.Watch/Watch/Aspire/AspireServiceFactory.cs | Adjusts API signature for start project (no longer returns RunningProject). |
| src/Dotnet.Watch/Watch/AppModels/WebApplicationAppModel.cs | Uses EnvironmentOptions.GetMuxerPath(). |
| src/Dotnet.Watch/Watch.Aspire/Utilities/AspireEnvironmentVariables.cs | New: reads pipe timeout (seconds) from env var. |
| src/Dotnet.Watch/Watch.Aspire/Server/WatchStatusWriter.cs | New: sends status JSON events via named pipe. |
| src/Dotnet.Watch/Watch.Aspire/Server/WatchStatusEvent.cs | New: status event contract. |
| src/Dotnet.Watch/Watch.Aspire/Server/WatchControlReader.cs | New: receives control commands and triggers targeted rebuild/restart. |
| src/Dotnet.Watch/Watch.Aspire/Server/WatchControlCommand.cs | New: control command contract. |
| src/Dotnet.Watch/Watch.Aspire/Server/StatusReportingLoggerFactory.cs | New: maps internal log notifications to status events. |
| src/Dotnet.Watch/Watch.Aspire/Server/ProcessLauncherFactory.cs | New: server-side resource request handling + output proxying. |
| src/Dotnet.Watch/Watch.Aspire/Server/AspireWatcherLauncher.cs | New: common launcher base for hosting watch server/host. |
| src/Dotnet.Watch/Watch.Aspire/Server/AspireServerLauncher.cs | New: server command launcher wiring (status/control pipe). |
| src/Dotnet.Watch/Watch.Aspire/Resource/LaunchResourceRequest.cs | New: resource launch request contract. |
| src/Dotnet.Watch/Watch.Aspire/Resource/AspireResourceLauncher.cs | New: resource command client (connect/send request/proxy output). |
| src/Dotnet.Watch/Watch.Aspire/Program.cs | Switches to new AspireLauncher command model + robust exception handling. |
| src/Dotnet.Watch/Watch.Aspire/Microsoft.DotNet.HotReload.Watch.Aspire.csproj | Adds MSBuild packages needed for registration/loading. |
| src/Dotnet.Watch/Watch.Aspire/Host/AspireHostLauncher.cs | New: host launcher building main project options. |
| src/Dotnet.Watch/Watch.Aspire/DotNetWatchOptions.cs | Removed legacy parsing/options type. |
| src/Dotnet.Watch/Watch.Aspire/DotNetWatchLauncher.cs | Removed legacy launcher wrapper. |
| src/Dotnet.Watch/Watch.Aspire/Commands/OptionExtensions.cs | New: option presence helper. |
| src/Dotnet.Watch/Watch.Aspire/Commands/AspireServerCommandDefinition.cs | New: server command/option definitions. |
| src/Dotnet.Watch/Watch.Aspire/Commands/AspireRootCommand.cs | New: root command composing host/server/resource. |
| src/Dotnet.Watch/Watch.Aspire/Commands/AspireResourceCommandDefinition.cs | New: resource command/option definitions + env var parsing. |
| src/Dotnet.Watch/Watch.Aspire/Commands/AspireHostCommandDefinition.cs | New: host command/option definitions. |
| src/Dotnet.Watch/Watch.Aspire/Commands/AspireCommandDefinition.cs | New: shared quiet/verbose validation + log level selection. |
| src/Dotnet.Watch/Watch.Aspire/AspireLauncher.cs | New: parsing + launcher dispatch for Aspire tool. |
| src/Dotnet.Watch/HotReloadClient/NamedPipeClientTransport.cs | Improves log message formatting. |
| src/Dotnet.Watch/HotReloadClient/DefaultHotReloadClient.cs | Logs full exception for response read failures. |
| src/Dotnet.Watch/Directory.Build.props | New: sets ProjectToolsProjectDir for Watch solution builds. |
| src/Dotnet.Watch/.editorconfig | New: suppresses analyzer/style warnings for Watch solution. |
test/Microsoft.DotNet.HotReload.Watch.Aspire.Tests/Utilities/PipeUtilities.cs
Show resolved
Hide resolved
| => new Logger(writer, underlyingFactory.CreateLogger(categoryName)); | ||
|
|
||
| public void AddProvider(ILoggerProvider provider) | ||
| => throw new NotImplementedException(); |
There was a problem hiding this comment.
ILoggerFactory.AddProvider throws NotImplementedException. If any code path adds providers to this factory (directly or via logging infrastructure), it will crash at runtime. Consider delegating to the underlying factory (or at least implementing this as a no-op if provider addition is intentionally unsupported).
| => throw new NotImplementedException(); | |
| { | |
| underlyingFactory.AddProvider(provider); | |
| } |
Test parallelization, improved diagnostics and robustness
Refactors test utilities for watching processes to simplify the implementation and make it more robust against potential race conditions.
All dotnet watch tests now run in ~2 minutes on a 48-core machine utilizing all cores most of the time.
Fixes #50228
Adds more functionality to Aspire.Watch CLI tool to support polyglot Aspire
Aspire invokes it via CLI. 3 CLI commands are currently available:
host,serverandresource.hostruns AppHost like an ordinarydotnet watchcommand:serverruns Hot Reload server and you pass it a set of C# resource projects or .cs files for file-based apps. It also takes a unique named pipe name to listen on:Optionally, it accepts
--status-pipeand-control-pipe. The former is used to send select event messages to AppHost, the latter allows the AppHost to restart a select project (or potentially issue other commands in future). See below.resourcelaunches a resource project:This command also takes parameters like
--environment,--launch-profile, etc.It sends request to launch an app to the server.
Status events (Watch Server → AppHost):
The watch server reports lifecycle events back to the AppHost over a named pipe (
--status-pipe). The AppHost uses these to update resource states in the Dashboard:building/build_complete(with success/failure)hot_reload_appliedrestartingprocess_started/process_exited(with exit code)Control commands (AppHost → Watch Server):
The AppHost sends commands to the watch server over a named pipe (
--control-pipe):rebuild— triggers a forced rebuild and restart for specific projects