Skip to content

Commit f78f6dc

Browse files
Copilotdanmoseley
andauthored
Audit and improve test coverage for all API parameter combinations
Agent-Logs-Url: https://github.com/dotnet/runtime/sessions/73a14058-c419-4277-b5e2-885c9c6c8607 Co-authored-by: danmoseley <6385855+danmoseley@users.noreply.github.com>
1 parent 391c3c4 commit f78f6dc

1 file changed

Lines changed: 79 additions & 0 deletions

File tree

  • src/libraries/System.Diagnostics.Process/tests

src/libraries/System.Diagnostics.Process/tests/RunTests.cs

Lines changed: 79 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -146,6 +146,85 @@ public async Task RunAndCaptureText_EmptyOutput(bool useAsync)
146146
Assert.Equal(string.Empty, result.StandardError);
147147
}
148148

149+
[ConditionalTheory(typeof(RemoteExecutor), nameof(RemoteExecutor.IsSupported))]
150+
[InlineData(false)]
151+
[InlineData(true)]
152+
public async Task RunAndCaptureText_WithTimeoutOrCancellation_CapturesOutput(bool useAsync)
153+
{
154+
using Process template = CreateProcess(static () =>
155+
{
156+
Console.Write("captured");
157+
Console.Error.Write("errors");
158+
return RemoteExecutor.SuccessExitCode;
159+
});
160+
161+
template.StartInfo.RedirectStandardOutput = true;
162+
template.StartInfo.RedirectStandardError = true;
163+
164+
ProcessTextOutput result;
165+
if (useAsync)
166+
{
167+
using var cts = new CancellationTokenSource(TimeSpan.FromMinutes(1));
168+
result = await Process.RunAndCaptureTextAsync(template.StartInfo, cts.Token);
169+
}
170+
else
171+
{
172+
result = Process.RunAndCaptureText(template.StartInfo, TimeSpan.FromMinutes(1));
173+
}
174+
175+
Assert.Equal(RemoteExecutor.SuccessExitCode, result.ExitStatus.ExitCode);
176+
Assert.False(result.ExitStatus.Canceled);
177+
Assert.Equal("captured", result.StandardOutput);
178+
Assert.Equal("errors", result.StandardError);
179+
}
180+
181+
[ConditionalTheory(typeof(RemoteExecutor), nameof(RemoteExecutor.IsSupported))]
182+
[InlineData(false)]
183+
[InlineData(true)]
184+
public async Task RunAndCaptureText_WithTimeoutOrCancellation_KillsLongRunningProcess(bool useAsync)
185+
{
186+
using Process template = CreateSleepProcess((int)TimeSpan.FromHours(1).TotalMilliseconds);
187+
188+
template.StartInfo.RedirectStandardOutput = true;
189+
template.StartInfo.RedirectStandardError = true;
190+
191+
if (useAsync)
192+
{
193+
await Assert.ThrowsAnyAsync<OperationCanceledException>(async () =>
194+
await Process.RunAndCaptureTextAsync(template.StartInfo, new CancellationTokenSource(TimeSpan.FromMilliseconds(100)).Token));
195+
}
196+
else
197+
{
198+
Assert.ThrowsAny<TimeoutException>(() =>
199+
Process.RunAndCaptureText(template.StartInfo, TimeSpan.FromMilliseconds(100)));
200+
}
201+
}
202+
203+
[Theory]
204+
[InlineData(false, false, true)]
205+
[InlineData(false, true, false)]
206+
[InlineData(false, false, false)]
207+
[InlineData(true, false, true)]
208+
[InlineData(true, true, false)]
209+
[InlineData(true, false, false)]
210+
public async Task RunAndCaptureText_NotRedirected_ThrowsInvalidOperationException(bool useAsync, bool redirectOutput, bool redirectError)
211+
{
212+
ProcessStartInfo startInfo = new("someprocess")
213+
{
214+
RedirectStandardOutput = redirectOutput,
215+
RedirectStandardError = redirectError
216+
};
217+
218+
if (useAsync)
219+
{
220+
await Assert.ThrowsAsync<InvalidOperationException>(() => Process.RunAndCaptureTextAsync(startInfo));
221+
}
222+
else
223+
{
224+
Assert.Throws<InvalidOperationException>(() => Process.RunAndCaptureText(startInfo));
225+
}
226+
}
227+
149228
[Theory]
150229
[InlineData(false)]
151230
[InlineData(true)]

0 commit comments

Comments
 (0)