diff --git a/eng/ManualVersions.props b/eng/ManualVersions.props
index 08821b070..0c141e3cb 100644
--- a/eng/ManualVersions.props
+++ b/eng/ManualVersions.props
@@ -9,10 +9,10 @@
Basically: In this file, choose the highest version when resolving merge conflicts.
-->
- 10.0.17763.23
- 10.0.18362.23
- 10.0.19041.23
- 10.0.20348.23
- 10.0.22000.23
+ 10.0.17763.24
+ 10.0.18362.24
+ 10.0.19041.24
+ 10.0.20348.24
+ 10.0.22000.24
diff --git a/src/SourceBuild/tarball/content/test/Microsoft.DotNet.SourceBuild.SmokeTests/DotNetHelper.cs b/src/SourceBuild/tarball/content/test/Microsoft.DotNet.SourceBuild.SmokeTests/DotNetHelper.cs
index ba011b06c..7c263e080 100644
--- a/src/SourceBuild/tarball/content/test/Microsoft.DotNet.SourceBuild.SmokeTests/DotNetHelper.cs
+++ b/src/SourceBuild/tarball/content/test/Microsoft.DotNet.SourceBuild.SmokeTests/DotNetHelper.cs
@@ -79,14 +79,25 @@ internal class DotNetHelper
}
}
- public void ExecuteCmd(string args, string? workingDirectory = null)
+ public void ExecuteCmd(string args, string? workingDirectory = null, Action? additionalProcessConfigCallback = null, int expectedExitCode = 0, int millisecondTimeout = -1)
{
+ Action configureProcess = (Process process, string? workingDirectory) => {
+ ConfigureProcess(process, workingDirectory);
+
+ if (additionalProcessConfigCallback != null)
+ {
+ additionalProcessConfigCallback(process);
+ }
+ };
+
(Process Process, string StdOut, string StdErr) executeResult = ExecuteHelper.ExecuteProcess(
DotNetPath,
args,
OutputHelper,
- configure: (process) => ConfigureProcess(process, workingDirectory));
- ExecuteHelper.ValidateExitCode(executeResult);
+ configure: (process) => configureProcess(process, workingDirectory),
+ millisecondTimeout: millisecondTimeout);
+
+ ExecuteHelper.ValidateExitCode(executeResult, expectedExitCode);
}
public static void ConfigureProcess(Process process, string? workingDirectory, bool setPath = false)
@@ -170,18 +181,14 @@ internal class DotNetHelper
public void ExecuteRunWeb(string projectName)
{
- (Process Process, string StdOut, string StdErr) executeResult = ExecuteHelper.ExecuteProcess(
- DotNetPath,
+ ExecuteCmd(
$"run {GetBinLogOption(projectName, "run")}",
- OutputHelper,
- configure: configureProcess,
+ GetProjectDirectory(projectName),
+ additionalProcessConfigCallback: processConfigCallback,
millisecondTimeout: 30000);
- ExecuteHelper.ValidateExitCode(executeResult);
- void configureProcess(Process process)
+ void processConfigCallback(Process process)
{
- ConfigureProcess(process, GetProjectDirectory(projectName));
-
process.OutputDataReceived += new DataReceivedEventHandler((sender, e) =>
{
if (e.Data?.Contains("Application started. Press Ctrl+C to shut down.") ?? false)
diff --git a/src/SourceBuild/tarball/content/test/Microsoft.DotNet.SourceBuild.SmokeTests/DotNetWatchTests.cs b/src/SourceBuild/tarball/content/test/Microsoft.DotNet.SourceBuild.SmokeTests/DotNetWatchTests.cs
new file mode 100644
index 000000000..183311037
--- /dev/null
+++ b/src/SourceBuild/tarball/content/test/Microsoft.DotNet.SourceBuild.SmokeTests/DotNetWatchTests.cs
@@ -0,0 +1,60 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+using System.Diagnostics;
+using System.IO;
+using Xunit;
+using Xunit.Abstractions;
+
+namespace Microsoft.DotNet.SourceBuild.SmokeTests;
+
+public class DotNetWatchTests : SmokeTests
+{
+ public DotNetWatchTests(ITestOutputHelper outputHelper) : base(outputHelper) { }
+
+ [Fact]
+ public void WatchTests()
+ {
+ string projectDirectory = DotNetHelper.ExecuteNew(DotNetTemplate.Console.GetName(), nameof(DotNetWatchTests));
+ bool outputChanged = false;
+
+ // We expect an exit code of 143 (128 + 15, i.e. SIGTERM) because we are killing the process manually
+ DotNetHelper.ExecuteCmd(
+ "watch run",
+ workingDirectory: projectDirectory,
+ additionalProcessConfigCallback: processConfigCallback,
+ expectedExitCode: 143,
+ millisecondTimeout: 30000);
+
+ Assert.True(outputChanged);
+
+ void processConfigCallback(Process process)
+ {
+ const string waitingString = "Waiting for a file to change before restarting dotnet...";
+ const string expectedString = "Hello from dotnet watch!";
+
+ bool fileChanged = false;
+
+ process.OutputDataReceived += new DataReceivedEventHandler((sender, e) =>
+ {
+ if (e.Data?.Contains(waitingString) ?? false)
+ {
+ if (!fileChanged) {
+ OutputHelper.WriteLine("Program started, changing file on disk to trigger restart...");
+ File.WriteAllText(
+ Path.Combine(projectDirectory, "Program.cs"),
+ File.ReadAllText(Path.Combine(projectDirectory, "Program.cs")).Replace("Hello, World!", expectedString));
+ fileChanged = true;
+ }
+ }
+ else if (e.Data?.Contains(expectedString) ?? false)
+ {
+ outputChanged = true;
+ OutputHelper.WriteLine("Successfully re-ran program after code change.");
+ ExecuteHelper.ExecuteProcessValidateExitCode("kill", $"-s TERM {process.Id}", OutputHelper);
+ }
+ });
+ }
+ }
+}
diff --git a/src/SourceBuild/tarball/content/test/Microsoft.DotNet.SourceBuild.SmokeTests/ExecuteHelper.cs b/src/SourceBuild/tarball/content/test/Microsoft.DotNet.SourceBuild.SmokeTests/ExecuteHelper.cs
index 5c135b3fe..4a7b87750 100644
--- a/src/SourceBuild/tarball/content/test/Microsoft.DotNet.SourceBuild.SmokeTests/ExecuteHelper.cs
+++ b/src/SourceBuild/tarball/content/test/Microsoft.DotNet.SourceBuild.SmokeTests/ExecuteHelper.cs
@@ -84,9 +84,9 @@ internal static class ExecuteHelper
return result.StdOut;
}
- public static void ValidateExitCode((Process Process, string StdOut, string StdErr) result)
+ public static void ValidateExitCode((Process Process, string StdOut, string StdErr) result, int expectedExitCode = 0)
{
- if (result.Process.ExitCode != 0)
+ if (result.Process.ExitCode != expectedExitCode)
{
ProcessStartInfo startInfo = result.Process.StartInfo;
string msg = $"Failed to execute {startInfo.FileName} {startInfo.Arguments}" +