tokio_process_tools/
lib.rs1#![warn(missing_docs)]
2
3#![doc = include_str!("../README.md")]
5mod collector;
8mod inspector;
9mod output;
10mod output_stream;
11mod panic_on_drop;
12mod process_handle;
13mod signal;
14mod terminate_on_drop;
15
16pub 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 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}