recmd/
cmd.rs

1///! Command module
2use std::process::Command;
3
4pub struct Cmd {
5    c: String,
6}
7
8impl Cmd {
9    pub fn new(s: &str) -> Self {
10        Cmd { c: String::from(s) }
11    }
12
13    pub fn run(&self) -> Result<Vec<u8>, String> {
14        match shell_words::split(&self.c) {
15            Ok(v) => {
16                let mut args = Vec::new();
17                if v.len() > 1 {
18                    args.extend(&v[1..]);
19                }
20                match Command::new(&v[0]).args(&args).output() {
21                    Ok(output) => {
22                        let mut out = output.stdout;
23
24                        if !output.stderr.is_empty() {
25                            out.extend(output.stderr);
26                        }
27
28                        Ok(out)
29                    }
30                    Err(e) => Err(format!("Failed to execute the command {} ({})", self.c, e)),
31                }
32            }
33            Err(_) => Err("Splitting error".to_string()),
34        }
35    }
36}
37
38#[cfg(test)]
39mod tests {
40    use super::Cmd;
41
42    #[test]
43    fn echo() {
44        let c = Cmd::new("echo \"test\"");
45        match c.run() {
46            Ok(o) => {
47                let ostr = String::from_utf8_lossy(&o);
48                assert_eq!("test\n", ostr);
49            }
50            Err(e) => {
51                println!("{}", e);
52                assert!(false);
53            }
54        }
55    }
56
57    #[test]
58    fn echo_no_new_line() {
59        let c = Cmd::new("echo -n \"test\"");
60        match c.run() {
61            Ok(o) => {
62                let ostr = String::from_utf8_lossy(&o);
63                assert_eq!("test", ostr);
64            }
65            Err(e) => {
66                println!("{}", e);
67                assert!(false);
68            }
69        }
70    }
71
72    #[test]
73    fn bash() {
74        let c = Cmd::new("bash -c 'VAR=test ; echo $VAR'");
75        match c.run() {
76            Ok(o) => {
77                let ostr = String::from_utf8_lossy(&o);
78                assert_eq!("test\n", ostr);
79            }
80            Err(e) => {
81                println!("{}", e);
82                assert!(false);
83            }
84        }
85    }
86
87    #[test]
88    fn bash_multiple_opts() {
89        let c = Cmd::new("bash -r -c 'VAR=test ; echo $VAR'");
90        match c.run() {
91            Ok(o) => {
92                let ostr = String::from_utf8_lossy(&o);
93                assert_eq!("test\n", ostr);
94            }
95            Err(e) => {
96                println!("{}", e);
97                assert!(false);
98            }
99        }
100    }
101
102    #[test]
103    fn command_does_not_exist() {
104        let c = Cmd::new("xxxxyyyytttt");
105        match c.run() {
106            Ok(_) => {
107                assert!(false);
108            }
109            Err(e) => {
110                println!("{}", e);
111                assert!(true);
112            }
113        }
114    }
115}