tendermint_testgen/
command.rs1use std::{
2 io::{self, Read},
3 process,
4};
5
6pub struct Command {
8 program: Option<String>,
9 args: Vec<String>,
10 dir: Option<String>,
11}
12
13pub struct CommandRun {
15 pub status: process::ExitStatus,
16 pub stdout: String,
17 pub stderr: String,
18}
19
20impl Command {
21 pub fn exists_program(program: &str) -> bool {
23 Command::new().program(program).spawn().is_ok()
24 }
25
26 pub fn new() -> Command {
28 Command {
29 program: None,
30 args: vec![],
31 dir: None,
32 }
33 }
34
35 pub fn program(&mut self, program: &str) -> &mut Self {
37 self.program = Some(program.to_owned());
38 self
39 }
40
41 pub fn arg(&mut self, arg: &str) -> &mut Self {
43 self.args.push(arg.to_owned());
44 self
45 }
46
47 pub fn arg_from_parts(&mut self, parts: Vec<&str>) -> &mut Self {
49 let arg = parts.join("");
50 self.args.push(arg);
51 self
52 }
53
54 pub fn current_dir(&mut self, dir: &str) -> &mut Self {
56 self.dir = Some(dir.to_owned());
57 self
58 }
59
60 pub fn spawn(&mut self) -> io::Result<CommandRun> {
62 match &self.program {
63 None => Err(io::Error::new(io::ErrorKind::InvalidInput, "")),
64 Some(program) => {
65 let mut command = process::Command::new(program);
66 command
67 .args(&self.args)
68 .stdout(process::Stdio::piped())
69 .stderr(process::Stdio::piped());
70 if let Some(dir) = &self.dir {
71 command.current_dir(dir);
72 }
73 let mut process = command.spawn()?;
74 let status = process.wait()?;
75 let mut stdout = String::new();
76 process.stdout.unwrap().read_to_string(&mut stdout)?;
77 let mut stderr = String::new();
78 process.stderr.unwrap().read_to_string(&mut stderr)?;
79 Ok(CommandRun {
80 status,
81 stdout,
82 stderr,
83 })
84 },
85 }
86 }
87}
88
89impl Default for Command {
90 fn default() -> Self {
91 Self::new()
92 }
93}