Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add test for System.Diagnostics.Process.Responding #46142

Merged
merged 9 commits into from
Dec 21, 2020
89 changes: 79 additions & 10 deletions src/libraries/System.Diagnostics.Process/tests/ProcessTests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@
using System.IO.Pipes;
using System.Linq;
using System.Net;
using System.Reflection;
using System.Security;
using System.Text;
using System.Threading;
Expand Down Expand Up @@ -1556,15 +1557,14 @@ public void MainWindowHandle_GetNotStarted_ThrowsInvalidOperationException()
var process = new Process();
Assert.Throws<InvalidOperationException>(() => process.MainWindowHandle);
}

[Fact]
[OuterLoop]
[Trait(XunitConstants.Category, XunitConstants.IgnoreForCI)] // Pops UI

[ConditionalFact(typeof(PlatformDetection), nameof(PlatformDetection.IsNotWindowsNanoServer))] // it needs Notepad
[OuterLoop("Pops UI")]
[PlatformSpecific(TestPlatforms.Windows)]
public void MainWindowHandle_GetWithGui_ShouldRefresh_Windows()
adamsitnik marked this conversation as resolved.
Show resolved Hide resolved
{
const string ExePath = "notepad.exe";
Assert.True(IsProgramInstalled(ExePath));
Assert.True(IsProgramInstalled(ExePath), "Notepad is not installed");

using (Process process = Process.Start(ExePath))
{
Expand All @@ -1591,16 +1591,15 @@ public void MainWindowHandle_GetWithGui_ShouldRefresh_Windows()
}
}

[Fact]
[OuterLoop]
[Trait(XunitConstants.Category, XunitConstants.IgnoreForCI)] // Pops UI
[ConditionalFact(typeof(PlatformDetection), nameof(PlatformDetection.IsNotWindowsNanoServer))] // it needs Notepad
[OuterLoop("Pops UI")]
[PlatformSpecific(TestPlatforms.Windows)]
public void MainWindowTitle_GetWithGui_ShouldRefresh_Windows()
{
const string ExePath = "notepad.exe";
Assert.True(IsProgramInstalled(ExePath));
Assert.True(IsProgramInstalled(ExePath), "Notepad is not installed");

using (Process process = Process.Start(ExePath))
using (Process process = Process.Start(new ProcessStartInfo(ExePath)))
{
try
{
Expand All @@ -1627,6 +1626,76 @@ public void MainWindowTitle_GetWithGui_ShouldRefresh_Windows()
}
}

[Fact]
public void RefreshResetsAllRefreshableFields()
{
// testing Process.Responding using a real unresponsive process would be very hard to do properly
// instead of this, we just test the implementation to ensure that #36768 is not coming back
var process = new Process();

VerifyPrivateFieldsValues(process, shouldHaveDefaultValues: true);

SetPrivateFieldsToNonDefaultValues(process);

VerifyPrivateFieldsValues(process, shouldHaveDefaultValues: false);

process.Refresh();

VerifyPrivateFieldsValues(process, shouldHaveDefaultValues: true);

static void VerifyPrivateFieldsValues(Process process, bool shouldHaveDefaultValues)
{
Assert.Equal(shouldHaveDefaultValues, !(bool)GetPrivateFieldValue(process, "_exited"));
Assert.Equal(shouldHaveDefaultValues, !(bool)GetPrivateFieldValue(process, "_haveWorkingSetLimits"));
Assert.Equal(shouldHaveDefaultValues, !(bool)GetPrivateFieldValue(process, "_haveProcessorAffinity"));
Assert.Equal(shouldHaveDefaultValues, !(bool)GetPrivateFieldValue(process, "_havePriorityClass"));
Assert.Equal(shouldHaveDefaultValues, !(bool)GetPrivateFieldValue(process, "_haveExitTime"));
Assert.Equal(shouldHaveDefaultValues, !(bool)GetPrivateFieldValue(process, "_havePriorityBoostEnabled"));

Assert.Equal(shouldHaveDefaultValues, null == GetPrivateFieldValue(process, "_processInfo"));
Assert.Equal(shouldHaveDefaultValues, null == GetPrivateFieldValue(process, "_threads"));
Assert.Equal(shouldHaveDefaultValues, null == GetPrivateFieldValue(process, "_modules"));

if (OperatingSystem.IsWindows())
{
Assert.Equal(shouldHaveDefaultValues, null == GetPrivateFieldValue(process, "_mainWindowTitle"));
Assert.Equal(shouldHaveDefaultValues, !(bool)GetPrivateFieldValue(process, "_signaled"));
Assert.Equal(shouldHaveDefaultValues, !(bool)GetPrivateFieldValue(process, "_haveMainWindow"));
Assert.Equal(shouldHaveDefaultValues, !(bool)GetPrivateFieldValue(process, "_haveResponding"));
}
}

static void SetPrivateFieldsToNonDefaultValues(Process process)
{
SetPrivateFieldValue(process, "_exited", true);
SetPrivateFieldValue(process, "_haveWorkingSetLimits", true);
SetPrivateFieldValue(process, "_haveProcessorAffinity", true);
SetPrivateFieldValue(process, "_havePriorityClass", true);
SetPrivateFieldValue(process, "_haveExitTime", true);
SetPrivateFieldValue(process, "_havePriorityBoostEnabled", true);

SetPrivateFieldValue(process, "_processInfo", typeof(Process).Assembly.GetType("System.Diagnostics.ProcessInfo").GetConstructor(BindingFlags.NonPublic | BindingFlags.Instance, Array.Empty<Type>()).Invoke(null));
SetPrivateFieldValue(process, "_threads", new ProcessThreadCollection(Array.Empty<ProcessThread>()));
SetPrivateFieldValue(process, "_modules", new ProcessModuleCollection(Array.Empty<ProcessModule>()));

if (OperatingSystem.IsWindows())
{
SetPrivateFieldValue(process, "_signaled", true);
SetPrivateFieldValue(process, "_haveMainWindow", true);
SetPrivateFieldValue(process, "_mainWindowTitle", "notNull");
SetPrivateFieldValue(process, "_haveResponding", true);
}
}

static object GetPrivateFieldValue(Process process, string fieldName) => typeof(Process)
.GetField(fieldName, BindingFlags.NonPublic | BindingFlags.Instance)
.GetValue(process);

static void SetPrivateFieldValue(Process process, string fieldName, object value) => typeof(Process)
.GetField(fieldName, BindingFlags.NonPublic | BindingFlags.Instance)
.SetValue(process, value);
}

[ConditionalFact(typeof(RemoteExecutor), nameof(RemoteExecutor.IsSupported))]
public void MainWindowTitle_NoWindow_ReturnsEmpty()
{
Expand Down