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()); }
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()); }
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(); }
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); }
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; }
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); }