tokio_process_tools/
lib.rs

1#![warn(missing_docs)]
2
3//!
4#![doc = include_str!("../README.md")]
5//!
6
7mod collector;
8mod inspector;
9mod output;
10mod output_stream;
11mod panic_on_drop;
12mod process_handle;
13mod signal;
14mod terminate_on_drop;
15
16/* public exports */
17pub use collector::{Collector, CollectorError, Sink};
18pub use inspector::{Inspector, InspectorError};
19pub use output::Output;
20pub use output_stream::{
21    LineOverflowBehavior, LineParsingOptions, Next, NumBytes, NumBytesExt, OutputStream, broadcast,
22    single_subscriber,
23};
24pub use process_handle::{ProcessHandle, RunningState, TerminationError, WaitError};
25pub use terminate_on_drop::TerminateOnDrop;
26
27#[cfg(test)]
28mod test {
29    use crate::output::Output;
30    use crate::output_stream::broadcast::BroadcastOutputStream;
31    use crate::{LineParsingOptions, ProcessHandle, RunningState};
32    use assertr::prelude::*;
33    use std::time::Duration;
34    use tokio::process::Command;
35
36    #[tokio::test]
37    async fn wait_with_output() {
38        let cmd = Command::new("ls");
39        let mut process = ProcessHandle::<BroadcastOutputStream>::spawn("ls", cmd)
40            .expect("Failed to spawn `ls` command");
41        let Output {
42            status,
43            stdout,
44            stderr,
45        } = process
46            .wait_for_completion_with_output(None, LineParsingOptions::default())
47            .await
48            .unwrap();
49        assert_that(status.success()).is_true();
50        assert_that(stdout).is_equal_to(&[
51            "Cargo.lock",
52            "Cargo.toml",
53            "LICENSE-APACHE",
54            "LICENSE-MIT",
55            "README.md",
56            "src",
57            "target",
58        ]);
59        assert_that(stderr).is_empty();
60    }
61
62    #[tokio::test]
63    async fn is_running() {
64        let mut cmd = Command::new("sleep");
65        cmd.arg("1");
66        let mut process = ProcessHandle::<BroadcastOutputStream>::spawn("sleep", cmd)
67            .expect("Failed to spawn `sleep` command");
68
69        match process.is_running() {
70            RunningState::Running => {}
71            RunningState::Terminated(exit_status) => {
72                assert_that(exit_status).fail("Process should be running");
73            }
74            RunningState::Uncertain(_) => {
75                assert_that_ref(&process).fail("Process state should not be uncertain");
76            }
77        };
78
79        let _exit_status = process.wait_for_completion(None).await.unwrap();
80
81        match process.is_running() {
82            RunningState::Running => {
83                assert_that(process).fail("Process should not be running anymore");
84            }
85            RunningState::Terminated(exit_status) => {
86                assert_that(exit_status.code()).is_some().is_equal_to(0);
87                assert_that(exit_status.success()).is_true();
88            }
89            RunningState::Uncertain(_) => {
90                assert_that(process).fail("Process state should not be uncertain");
91            }
92        };
93    }
94
95    #[tokio::test]
96    async fn terminate() {
97        let mut cmd = Command::new("sleep");
98        cmd.arg("1000");
99        let mut process = ProcessHandle::<BroadcastOutputStream>::spawn("sleep", cmd)
100            .expect("Failed to spawn `sleep` command");
101        process
102            .terminate(Duration::from_secs(1), Duration::from_secs(1))
103            .await
104            .unwrap();
105        match process.is_running() {
106            RunningState::Running => {
107                assert_that(process).fail("Process should not be running anymore");
108            }
109            RunningState::Terminated(exit_status) => {
110                // Terminating a process with a signal results in no code being emitted (on linux).
111                assert_that(exit_status.code()).is_none();
112                assert_that(exit_status.success()).is_false();
113            }
114            RunningState::Uncertain(_) => {
115                assert_that(process).fail("Process state should not be uncertain");
116            }
117        };
118    }
119}