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);
        }
Exemple #6
0
        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}'");
        }
Exemple #10
0
        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();
        }
Exemple #11
0
        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);
        }
Exemple #13
0
        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());
        }
Exemple #16
0
        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);
        }
Exemple #17
0
        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);
        }
Exemple #19
0
        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);
        }
Exemple #20
0
        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);
        }
Exemple #28
0
        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");
        }