public async Task Given_short_running_exe_then_should_run_to_exit()
        {
            var envVars = new StringDictionary {
                { "a", "b" }
            };
            var supervisor = new ProcessSupervisor(
                _loggerFactory,
                ProcessRunType.SelfTerminating,
                Environment.CurrentDirectory,
                "dotnet",
                "./SelfTerminatingProcess/SelfTerminatingProcess.dll",
                envVars);

            supervisor.OutputDataReceived += data => _outputHelper.WriteLine2(data);
            var whenStateIsExited          = supervisor.WhenStateIs(ProcessSupervisor.State.ExitedSuccessfully);
            var whenStateIsExitedWithError = supervisor.WhenStateIs(ProcessSupervisor.State.ExitedWithError);

            await supervisor.Start();

            var task = await Task.WhenAny(whenStateIsExited, whenStateIsExitedWithError);

            task.ShouldBe(whenStateIsExited);
            supervisor.CurrentState.ShouldBe(ProcessSupervisor.State.ExitedSuccessfully);
            supervisor.OnStartException.ShouldBeNull();
            supervisor.ProcessInfo.ExitCode.ShouldBe(0);
        }
        public async Task Can_restart_a_stopped_long_running_process()
        {
            var supervisor = new ProcessSupervisor(
                _loggerFactory,
                ProcessRunType.NonTerminating,
                Environment.CurrentDirectory,
                "dotnet",
                "./NonTerminatingProcess/NonTerminatingProcess.dll");

            supervisor.OutputDataReceived += data => _outputHelper.WriteLine2(data);
            var exitedKilled = supervisor.WhenStateIs(ProcessSupervisor.State.ExitedKilled);
            await supervisor.Start();

            await supervisor.Stop();

            await exitedKilled.TimeoutAfter(TimeSpan.FromSeconds(5));

            // Restart
            var exitedSuccessfully = supervisor.WhenStateIs(ProcessSupervisor.State.ExitedSuccessfully);
            await supervisor.Start();

            await supervisor.Stop(TimeSpan.FromSeconds(2));

            await exitedSuccessfully;
        }
        public async Task When_parent_process_exits_than_should_call_parent_exited_callback()
        {
            // Start parent
            var supervisor = new ProcessSupervisor(
                ProcessRunType.NonTerminating,
                Environment.CurrentDirectory,
                "dotnet",
                "./NonTerminatingProcess/NonTerminatingProcess.dll");
            var parentIsRunning = supervisor.WhenStateIs(ProcessSupervisor.State.Running);

            supervisor.OutputDataReceived += data => _outputHelper.WriteLine($"Parent Process: {data}");
            supervisor.Start();
            await parentIsRunning;

            // Monitor parent
            var parentExited = new TaskCompletionSource <int?>();

            using (new ProcessExitedHelper(supervisor.ProcessInfo.Id, watcher => parentExited.SetResult(watcher.ProcessId)))
            {
                // Stop parent
                await supervisor.Stop(TimeSpan.FromSeconds(2));

                var processId = await parentExited.Task.TimeoutAfter(TimeSpan.FromSeconds(2));

                processId.Value.ShouldBeGreaterThan(0);
            }
        }
        public async Task When_parent_process_exits_then_child_process_should_also_do_so()
        {
            // Start parent
            var parentSupervisor = new ProcessSupervisor(
                ProcessRunType.NonTerminating,
                Environment.CurrentDirectory,
                "dotnet",
                "./NonTerminatingProcess/NonTerminatingProcess.dll");

            parentSupervisor.OutputDataReceived += data => _outputHelper.WriteLine($"Parent: {data}");
            var parentIsRunning = parentSupervisor.WhenStateIs(ProcessSupervisor.State.Running);

            parentSupervisor.Start();
            await parentIsRunning;

            // Start child
            var childSupervisor = new ProcessSupervisor(
                ProcessRunType.SelfTerminating,
                Environment.CurrentDirectory,
                "dotnet",
                $"./NonTerminatingProcess/NonTerminatingProcess.dll --ParentProcessId={parentSupervisor.ProcessInfo.Id}");

            childSupervisor.OutputDataReceived += data => _outputHelper.WriteLine($"Child: {data}");
            var childIsRunning  = childSupervisor.WhenStateIs(ProcessSupervisor.State.Running);
            var childHasStopped = childSupervisor.WhenStateIs(ProcessSupervisor.State.ExitedSuccessfully);

            childSupervisor.Start();
            await childIsRunning;

            // Stop parent
            await parentSupervisor.Stop(TimeSpan.FromSeconds(2));

            // Wait for child to stop
            await childHasStopped.TimeoutAfter(TimeSpan.FromSeconds(2));
        }
        public async Task Given_invalid_working_directory_then_state_should_be_StartError()
        {
            var supervisor = new ProcessSupervisor(_loggerFactory, ProcessRunType.NonTerminating, "c:/does_not_exist", "git.exe");
            await supervisor.Start();

            supervisor.CurrentState.ShouldBe(ProcessSupervisor.State.StartFailed);
            supervisor.OnStartException.ShouldNotBeNull();

            _outputHelper.WriteLine(supervisor.OnStartException.ToString());
        }
        public void WriteDotGraph()
        {
            var processController = new ProcessSupervisor(
                _loggerFactory,
                ProcessRunType.NonTerminating,
                Environment.CurrentDirectory,
                "invalid.exe");

            _outputHelper.WriteLine(processController.GetDotGraph());
        }
Exemple #7
0
        public void Given_invalid_process_path_then_state_should_be_StartError()
        {
            var supervisor = new ProcessSupervisor(ProcessRunType.NonTerminating, "c:/", "invalid.exe");

            supervisor.Start();

            supervisor.CurrentState.ShouldBe(ProcessSupervisor.State.StartFailed);
            supervisor.Exception.ShouldNotBeNull();

            _outputHelper.WriteLine(supervisor.Exception.ToString());
        }
        public async Task Given_invalid_process_path_then_state_should_be_StartError()
        {
            var supervisor         = new ProcessSupervisor(_loggerFactory, ProcessRunType.NonTerminating, "c:/", "invalid.exe");
            var stateIsStartFailed = supervisor.WhenStateIs(ProcessSupervisor.State.StartFailed);
            await supervisor.Start();

            await stateIsStartFailed;

            supervisor.CurrentState.ShouldBe(ProcessSupervisor.State.StartFailed);
            supervisor.OnStartException.ShouldNotBeNull();

            _outputHelper.WriteLine(supervisor.OnStartException.ToString());
        }
Exemple #9
0
        public void Can_attempt_to_restart_a_failed_short_running_process()
        {
            var supervisor = new ProcessSupervisor(ProcessRunType.NonTerminating, Environment.CurrentDirectory, "invalid.exe");

            supervisor.Start();

            supervisor.CurrentState.ShouldBe(ProcessSupervisor.State.StartFailed);
            supervisor.Exception.ShouldNotBeNull();

            supervisor.Start();

            supervisor.CurrentState.ShouldBe(ProcessSupervisor.State.StartFailed);
            supervisor.Exception.ShouldNotBeNull();
        }
Exemple #10
0
        public async Task When_stop_a_non_terminating_process_then_should_exit_successfully()
        {
            var supervisor = new ProcessSupervisor(ProcessRunType.NonTerminating, Environment.CurrentDirectory, "dotnet", "./LongRunningProcess/LongRunningProcess.dll");

            supervisor.OutputDataReceived += data => _outputHelper.WriteLine2(data);
            var stateIsStopped = supervisor.WhenStateIs(ProcessSupervisor.State.ExitedSuccessfully);

            supervisor.Start();
            await supervisor.Stop(); // No timeout so will just kill the process

            await stateIsStopped.TimeoutAfter(TimeSpan.FromSeconds(2));

            _outputHelper.WriteLine($"Exit code {supervisor.ProcessInfo.ExitCode}");
        }
        public static Task WhenOutputStartsWith(this ProcessSupervisor processSupervisor, string startsWith)
        {
            var taskCompletionSource = new TaskCompletionSource <int>();

            void Handler(string data)
            {
                if (data.StartsWith(startsWith))
                {
                    taskCompletionSource.SetResult(0);
                    processSupervisor.OutputDataReceived -= Handler;
                }
            }

            processSupervisor.OutputDataReceived += Handler;
            return(taskCompletionSource.Task);
        }
        public static Task WhenStateIs(this ProcessSupervisor processSupervisor, ProcessSupervisor.State processState)
        {
            var taskCompletionSource = new TaskCompletionSource <int>();

            void Handler(ProcessSupervisor.State state)
            {
                if (processState == state)
                {
                    taskCompletionSource.SetResult(0);
                    processSupervisor.StateChanged -= Handler;
                }
            }

            processSupervisor.StateChanged += Handler;
            return(taskCompletionSource.Task);
        }
Exemple #13
0
        public async Task Can_restart_a_stopped_short_running_process()
        {
            var supervisor = new ProcessSupervisor(
                ProcessRunType.SelfTerminating,
                Environment.CurrentDirectory,
                "dotnet",
                "./SelfTerminatingProcess/SelfTerminatingProcess.dll");

            supervisor.OutputDataReceived += data => _outputHelper.WriteLine2(data);
            var stateIsStopped = supervisor.WhenStateIs(ProcessSupervisor.State.ExitedSuccessfully);

            supervisor.Start();
            await stateIsStopped;

            supervisor.Start();
            await stateIsStopped;
        }
Exemple #14
0
        public async Task Given_short_running_exe_then_should_run_to_exit()
        {
            var supervisor = new ProcessSupervisor(
                ProcessRunType.SelfTerminating,
                Environment.CurrentDirectory,
                "dotnet",
                "./SelfTerminatingProcess/SelfTerminatingProcess.dll");

            supervisor.OutputDataReceived += data => _outputHelper.WriteLine2(data);
            var whenStateIsExited = supervisor.WhenStateIs(ProcessSupervisor.State.ExitedSuccessfully);

            supervisor.Start();
            await whenStateIsExited;

            supervisor.CurrentState.ShouldBe(ProcessSupervisor.State.ExitedSuccessfully);
            supervisor.Exception.ShouldBeNull();
            supervisor.ProcessInfo.ExitCode.ShouldBe(0);
        }
        public async Task When_stop_a_non_terminating_process_that_does_not_shutdown_within_timeout_then_should_exit_killed()
        {
            var supervisor = new ProcessSupervisor(
                _loggerFactory,
                ProcessRunType.NonTerminating,
                Environment.CurrentDirectory,
                "dotnet",
                "./NonTerminatingProcess/NonTerminatingProcess.dll --ignore-shutdown-signal=true");

            supervisor.OutputDataReceived += data => _outputHelper.WriteLine2(data);
            var stateIsKilled = supervisor.WhenStateIs(ProcessSupervisor.State.ExitedKilled);
            await supervisor.Start();

            await supervisor.Stop(TimeSpan.FromSeconds(2));

            await stateIsKilled.TimeoutAfter(TimeSpan.FromSeconds(5));

            _outputHelper.WriteLine($"Exit code {supervisor.ProcessInfo.ExitCode}");
        }
        public static Task WhenOutputStartsWith(
            this ProcessSupervisor processSupervisor,
            string startsWith,
            CancellationToken cancellationToken = default)
        {
            var taskCompletionSource = new TaskCompletionSource <int>();

            cancellationToken.Register(() => taskCompletionSource.TrySetCanceled());

            void Handler(string data)
            {
                if (data.StartsWith(startsWith))
                {
                    taskCompletionSource.SetResult(0);
                    processSupervisor.OutputDataReceived -= Handler;
                }
            }

            processSupervisor.OutputDataReceived += Handler;
            return(taskCompletionSource.Task);
        }
        public async Task When_stop_a_non_terminating_process_with_non_zero_then_should_exit_error()
        {
            var supervisor = new ProcessSupervisor(
                _loggerFactory,
                ProcessRunType.NonTerminating,
                Environment.CurrentDirectory,
                "dotnet",
                "./NonTerminatingProcess/NonTerminatingProcess.dll --exit-with-non-zero=true");

            supervisor.OutputDataReceived += data => _outputHelper.WriteLine2(data);
            var stateExitWithError = supervisor.WhenStateIs(ProcessSupervisor.State.ExitedWithError);
            await supervisor.Start();

            await supervisor.Stop(TimeSpan.FromSeconds(5));

            await stateExitWithError.TimeoutAfter(TimeSpan.FromSeconds(5));

            supervisor.ProcessInfo.ExitCode.ShouldNotBe(0);

            _outputHelper.WriteLine($"Exit code {supervisor.ProcessInfo.ExitCode}");
        }
        public async Task Given_non_terminating_process_then_should_exit_when_stopped()
        {
            var supervisor = new ProcessSupervisor(
                _loggerFactory,
                ProcessRunType.NonTerminating,
                Environment.CurrentDirectory,
                "dotnet",
                "./NonTerminatingProcess/NonTerminatingProcess.dll");

            supervisor.OutputDataReceived += data => _outputHelper.WriteLine2($"Process: {data}");
            var running = supervisor.WhenStateIs(ProcessSupervisor.State.Running);
            await supervisor.Start();

            supervisor.CurrentState.ShouldBe(ProcessSupervisor.State.Running);
            await running;

            await supervisor.Stop(TimeSpan.FromSeconds(5));

            supervisor.CurrentState.ShouldBe(ProcessSupervisor.State.ExitedSuccessfully);
            supervisor.OnStartException.ShouldBeNull();
            supervisor.ProcessInfo.ExitCode.ShouldBe(0);
        }
        public static Task WhenStateIs(
            this ProcessSupervisor processSupervisor,
            ProcessSupervisor.State processState,
            CancellationToken cancellationToken = default)
        {
            var taskCompletionSource = new TaskCompletionSource <int>();

            cancellationToken.Register(() => taskCompletionSource.TrySetCanceled());

            void Handler(ProcessSupervisor.State state)
            {
                if (processState == state)
                {
                    taskCompletionSource.SetResult(0);
                    processSupervisor.StateChanged -= Handler;
                }
            }

            processSupervisor.StateChanged += Handler;

            return(taskCompletionSource.Task);
        }