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