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