public void TestToString() { var sampleCommandString = #if NETCOREAPP2_2 $@"{DotNetPath} {SampleCommand}"; #else SampleCommand; #endif var command0 = TestShell.Run(SampleCommand, new[] { "grep", "a+" }, options => options.DisposeOnExit(true)); command0.ToString().ShouldEqual($"{sampleCommandString} grep a+"); var command1 = TestShell.Run(SampleCommand, "exit", 0); command1.ToString().ShouldEqual($"{sampleCommandString} exit 0"); var command2 = TestShell.Run(SampleCommand, "ex it", "0 0"); command2.ToString().ShouldEqual($"{sampleCommandString} \"ex it\" \"0 0\""); var command3 = command1 < new[] { "a" }; command3.ToString().ShouldEqual($"{sampleCommandString} exit 0 < System.String[]"); var command4 = command3 | TestShell.Run(SampleCommand, "echo"); command4.ToString().ShouldEqual($"{sampleCommandString} exit 0 < System.String[] | {sampleCommandString} echo"); var command5 = command2.RedirectStandardErrorTo(Stream.Null); command5.ToString().ShouldEqual($"{sampleCommandString} \"ex it\" \"0 0\" 2> {Stream.Null}"); var command6 = command5.RedirectTo(new StringWriter()); command6.Wait(); command6.ToString().ShouldEqual($"{command5} > {new StringWriter()}"); }
public void TestNestedKill() { var lines = new SyncCollection(); var pipeline = TestShell.Run(SampleCommand, "pipe") | TestShell.Run(SampleCommand, "pipe") | TestShell.Run(SampleCommand, "pipe") > lines; // demonstrate that a single line can make it all the way through the pipeline // without getting caught in a buffer along the way pipeline.StandardInput.AutoFlush.ShouldEqual(true); pipeline.StandardInput.WriteLine("a line"); var start = DateTime.UtcNow; while ((DateTime.UtcNow - start) < TimeSpan.FromSeconds(10)) { if (lines.Count > 0) { break; } Thread.Sleep(10); } pipeline.Task.IsCompleted.ShouldEqual(false); lines.FirstOrDefault().ShouldEqual("a line"); pipeline.Task.IsCompleted.ShouldEqual(false); pipeline.Kill(); pipeline.Result.Success.ShouldEqual(false); }
public void TestLongWriteWithInfrequentReads() { var lines = Enumerable.Range(0, 100).Select(i => i.ToString()) .ToArray(); var command = TestShell.Run(SampleCommand, "grep", ".") < lines; var outputLines = new List <string>(); var readTask = Task.Run(() => { var rand = new Random(12345); while (true) { if (rand.Next(10) == 0) { Thread.Sleep(200); } else { var line = command.StandardOutput.ReadLine(); if (line == null) { return; } else { outputLines.Add(line); } } } }); Task.WaitAll(command.Task, readTask); string.Join("/", outputLines).ShouldEqual(string.Join("/", lines)); }
public void TestZeroTimeout() { var willTimeout = TestShell.Run(SampleCommand, new object[] { "sleep", 1000000 }, o => o.Timeout(TimeSpan.Zero)); var ex = Assert.Throws <AggregateException>(() => willTimeout.Task.Wait()); Assert.IsInstanceOf <TimeoutException>(ex.InnerException); }
private void TestRealRoundTrip(string[] arguments) { var output = TestShell.Run(SampleCommand, new[] { "argecho" }.Concat(arguments), o => o.ThrowOnError()).Result.StandardOutput; var expected = string.Join(string.Empty, arguments.Select(a => a + Environment.NewLine)); output.ShouldEqual(expected); }
public void TestProcessKeepsWritingAfterOutputIsClosed() { var command = TestShell.Run(SampleCommand, new[] { "pipe" }); command.StandardOutput.Dispose(); for (var i = 0; i < 100; ++i) { command.StandardInput.WriteLine(new string('a', i)); } // workaround for https://github.com/mono/mono/issues/18279; so far // I've encountered this only on Mono Linux if (PlatformCompatibilityHelper.IsMono && !RuntimeInformation.IsOSPlatform(OSPlatform.Windows)) { command.StandardInput.Dispose(); command.Task.Wait(TimeSpan.FromSeconds(1000)).ShouldEqual(true); command.Result.ExitCode.ShouldEqual(1); // SampleCommand fails because it's attempt to write to Console.Out fails hard Assert.That(command.Result.StandardError, Does.Contain("System.IO.IOException: Write fault")); } else { command.Task.IsCompleted.ShouldEqual(false); command.StandardInput.Dispose(); command.Task.Wait(TimeSpan.FromSeconds(1000)).ShouldEqual(true); command.Result.Success.ShouldEqual(true); } }
public void TestKillAfterFinished() { var command = TestShell.Run(SampleCommand, "bool", true, "something"); command.Task.Wait(); command.Kill(); command.Result.Success.ShouldEqual(true); }
public void TestThrowOnErrorWithTimeout() { var command = TestShell.Run(SampleCommand, new object[] { "exit", 1 }, o => o.ThrowOnError().Timeout(TimeSpan.FromDays(1))); var ex = Assert.Throws <AggregateException>(() => command.Task.Wait()); ex.InnerExceptions.Select(e => e.GetType()).SequenceEqual(new[] { typeof(ErrorExitCodeException) }) .ShouldEqual(true); }
public void TestGrep() { var command = TestShell.Run(SampleCommand, "grep", "a+"); command.StandardInput.WriteLine("hi"); command.StandardInput.WriteLine("aa"); command.StandardInput.Dispose(); command.StandardOutput.ReadToEnd().ShouldEqual("aa" + Environment.NewLine, $"Exit code: {command.Result.ExitCode}, StdErr: '{command.Result.StandardError}'"); }
public void TestAttachingToExistingProcess() { var processCommand = TestShell.Run(SampleCommand, new[] { "sleep", "10000" }); var processId = processCommand.ProcessId; Command.TryAttachToProcess(processId, out _) .ShouldEqual(true, "Attaching to process failed."); processCommand.Kill(); }
public void TestAttachingToNonExistingProcess() { var processCommand = TestShell.Run(SampleCommand, new[] { "exit", "0" }); var processId = processCommand.ProcessId; processCommand.Task.Wait(1000).ShouldEqual(true, "Process has not exited, test is inconclusive."); Command.TryAttachToProcess(processId, out _) .ShouldEqual(false, "Attaching succeeded although process has already exited."); }
public async Task CanSendControlCToPipeline() { var command = TestShell.Run(SampleCommand, "sleep", "10000") | TestShell.Run(SampleCommand, "pipe") | TestShell.Run(SampleCommand, "pipe"); (await command.TrySignalAsync(CommandSignal.ControlC)).ShouldEqual(true); command.Task.Wait(TimeSpan.FromSeconds(5)).ShouldEqual(true); }
public void TestCancellationAlreadyCanceled() { using var alreadyCanceled = new CancellationTokenSource(millisecondsDelay: 0); var command = TestShell.Run(SampleCommand, new object[] { "sleep", 1000000 }, o => o.CancellationToken(alreadyCanceled.Token)); Assert.Throws <TaskCanceledException>(() => command.Wait()); Assert.Throws <TaskCanceledException>(() => command.Result.ToString()); command.Task.Status.ShouldEqual(TaskStatus.Canceled); Assert.DoesNotThrow(() => command.ProcessId.ToString(), "still executes a command and gets a process ID"); }
public void TestShortFlush() { var command = TestShell.Run(SampleCommand, "shortflush", "a"); var readCommand = command.StandardOutput.ReadBlockAsync(new char[1], 0, 1); readCommand.Wait(TimeSpan.FromSeconds(5)).ShouldEqual(true); command.StandardInput.Dispose(); command.Task.Wait(TimeSpan.FromSeconds(5)).ShouldEqual(true); }
public void TestErrorHandling() { var command = TestShell.Run(SampleCommand, "echo") < "abc" > new char[0]; Assert.Throws <NotSupportedException>(() => command.Wait()); var command2 = TestShell.Run(SampleCommand, "echo") < this.ErrorLines(); Assert.Throws <InvalidOperationException>(() => command2.Wait()); }
public void TestCancellationNotCanceled() { using var notCanceled = new CancellationTokenSource(); var command = TestShell.Run(SampleCommand, new object[] { "sleep", 1000000 }, o => o.CancellationToken(notCanceled.Token)); command.Task.Wait(50).ShouldEqual(false); command.Kill(); command.Task.Wait(1000).ShouldEqual(true); command.Result.Success.ShouldEqual(false); }
public void TestGettingExitCodeFromAttachedProcess() { var processCommand = TestShell.Run(SampleCommand, new[] { "exit", "16" }); Command.TryAttachToProcess(processCommand.ProcessId, out var attachedCommand) .ShouldEqual(true, "Attaching to process failed."); var task = attachedCommand !.Task; task.Wait(1000).ShouldEqual(true, "Task has not finished on time."); task.Result.ExitCode.ShouldEqual(16, "Exit code was not correct."); }
public void TestPipedGrep() { Log.WriteLine("******** TestPipedGrep starting *********"); var command = TestShell.Run(SampleCommand, "grep", "a") < new[] { "abcd", "a", "ab", "abc" } | TestShell.Run(SampleCommand, "grep", "b") | TestShell.Run(SampleCommand, "grep", "c"); var results = command.StandardOutput.GetLines().ToArray(); results.SequenceEqual(new[] { "abcd", "abc" }).ShouldEqual(true); }
public void TestCancellationCanceledAfterCompletion() { using var cancellationTokenSource = new CancellationTokenSource(); var results = new List <string>(); var command = TestShell.Run(SampleCommand, new object[] { "echo" }, o => o.CancellationToken(cancellationTokenSource.Token)) > results; command.StandardInput.WriteLine("hello"); command.StandardInput.Close(); command.Task.Wait(1000).ShouldEqual(true); cancellationTokenSource.Cancel(); command.Result.Success.ShouldEqual(true); }
public void TestWaitingForAttachedProcessExit() { var processCommand = TestShell.Run(SampleCommand, new[] { "sleep", "100" }); Command.TryAttachToProcess(processCommand.ProcessId, out var attachedCommand) .ShouldEqual(true, "Attaching to process failed."); var commandResult = attachedCommand !.Task; commandResult.IsCompleted.ShouldEqual(false, "Task has finished too early."); Thread.Sleep(300); commandResult.IsCompleted.ShouldEqual(true, "Task has not finished on time."); }
public void TestCancellationWithTimeoutCancellationWins() { var cancellationTokenSource = new CancellationTokenSource(TimeSpan.FromMilliseconds(50)); var command = TestShell.Run( SampleCommand, new object[] { "sleep", 1000000 }, o => o.CancellationToken(cancellationTokenSource.Token) .Timeout(TimeSpan.FromSeconds(5)) ); Assert.Throws <TaskCanceledException>(() => command.Wait()); }
public async Task CanSendControlC() { var command = TestShell.Run(SampleCommand, "sleep", "10000"); if (RuntimeInformation.IsOSPlatform(OSPlatform.Windows)) { WindowsProcessSignaler.HasSameConsole(command.ProcessId).ShouldEqual(false, "sanity check console setup"); } (await command.TrySignalAsync(CommandSignal.ControlC)).ShouldEqual(true); command.Task.Wait(TimeSpan.FromSeconds(5)).ShouldEqual(true); }
public async Task CanSendUnixSignal([Values(3 /* SIGQUIT */, 6 /* SIGABORT */, 9 /* SIGKILL */)] int unixSignal) { if (RuntimeInformation.IsOSPlatform(OSPlatform.Windows)) { Assert.Pass("tests unix-specific behavior"); } var command = TestShell.Run(SampleCommand, "sleep", "10000"); (await command.TrySignalAsync(CommandSignal.ControlC)).ShouldEqual(true); command.Task.Wait(TimeSpan.FromSeconds(5)).ShouldEqual(true); }
public void TestExitCode() { Assert.IsTrue(TestShell.Run(SampleCommand, "exit", 0).Result.Success); Assert.IsFalse(TestShell.Run(SampleCommand, "exit", 1).Result.Success); var shell = MakeTestShell(o => o.ThrowOnError()); var ex = Assert.Throws <AggregateException>(() => shell.Run(SampleCommand, "exit", -1).Task.Wait()); ex.InnerExceptions.Select(e => e.GetType()).SequenceEqual(new[] { typeof(ErrorExitCodeException) }) .ShouldEqual(true); shell.Run(SampleCommand, "exit", 0).Task.Wait(); }
public async Task HandlesEdgeCases() { var command = TestShell.Run(SampleCommand, "sleep", "10000"); Assert.Throws <ArgumentNullException>(() => command.TrySignalAsync(null).GetType()); command.Kill(); await command.Task; (await command.TrySignalAsync(CommandSignal.ControlC)).ShouldEqual(false, "exited"); command.As <IDisposable>().Dispose(); Assert.Throws <ObjectDisposedException>(() => command.TrySignalAsync(CommandSignal.ControlC).GetType()); }
public void TestProcessKeepsWritingAfterOutputIsClosed() { var command = TestShell.Run(SampleCommand, new[] { "pipe" }, options: o => o.ThrowOnError()); command.StandardOutput.Dispose(); for (var i = 0; i < 100; ++i) { command.StandardInput.WriteLine(new string('a', i)); } command.Task.IsCompleted.ShouldEqual(false); command.StandardInput.Dispose(); command.Task.Wait(TimeSpan.FromSeconds(1000)).ShouldEqual(true); }
public void TestStandardInputCannotBeAccessedAfterRedirectingIt() { var command = TestShell.Run(SampleCommand, "echo"); var ioCommand = command.RedirectFrom(new[] { "a" }); var errorMessage = Assert.Throws <InvalidOperationException>(() => ioCommand.StandardInput.GetHashCode()).Message; errorMessage.ShouldEqual("StandardInput is unavailable because it is already being piped from System.String[]"); Assert.DoesNotThrow(() => command.StandardInput.GetHashCode()); ioCommand.Result.StandardOutput.ShouldEqual(command.Result.StandardOutput).ShouldEqual($"a{Environment.NewLine}"); ioCommand.Result.StandardError.ShouldEqual(command.Result.StandardError).ShouldEqual(string.Empty); }
public void TestKillingAttachedProcess() { var processCommand = TestShell.Run(SampleCommand, new[] { "sleep", "10000" }); var processId = processCommand.ProcessId; Command.TryAttachToProcess( processId, out var attachedCommand) .ShouldEqual(true, "Attaching to process failed."); attachedCommand !.Kill(); attachedCommand.Task.Wait(TimeSpan.FromSeconds(1)) .ShouldEqual(true, "The process is still alive after Kill() has finished."); }
public void TestCommandOption() { var command = TestShell.Run(SampleCommand, new[] { "echo" }, options: o => o.Command(c => c.StandardInput.Write("!!!"))) .RedirectFrom("abc"); command.Wait(); command.Result.StandardOutput.ShouldEqual("!!!abc"); var writer = new StringWriter(); command = TestShell.Run(SampleCommand, new[] { "echo" }, options: o => o.Command(c => c.RedirectTo(writer))) .RedirectFrom("abc123"); command.Wait(); writer.ToString().ShouldEqual("abc123"); }
public void TestKill() { var command = TestShell.Run(SampleCommand, "pipe"); command.StandardInput.WriteLine("abc"); command.StandardInput.Flush(); Thread.Sleep(300); command.Task.IsCompleted.ShouldEqual(false); command.Kill(); command.Result.Success.ShouldEqual(false); // https://www.tldp.org/LDP/abs/html/exitcodes.html command.Result.ExitCode.ShouldEqual(RuntimeInformation.IsOSPlatform(OSPlatform.Windows) ? -1 : 137); command.StandardOutput.ReadLine().ShouldEqual("abc"); }