lmrc_ssh/output.rs
1//! Command output types.
2
3/// The output of an executed SSH command.
4///
5/// Contains the standard output, standard error, and exit status
6/// of the executed command.
7#[derive(Debug, Clone, PartialEq, Eq)]
8pub struct CommandOutput {
9 /// The standard output from the command.
10 pub stdout: String,
11
12 /// The standard error from the command.
13 pub stderr: String,
14
15 /// The exit status code of the command.
16 /// 0 typically indicates success, while non-zero indicates an error.
17 pub exit_status: i32,
18}
19
20impl CommandOutput {
21 /// Creates a new `CommandOutput` instance.
22 ///
23 /// # Arguments
24 ///
25 /// * `stdout` - The standard output from the command
26 /// * `stderr` - The standard error from the command
27 /// * `exit_status` - The exit status code
28 ///
29 /// # Examples
30 ///
31 /// ```
32 /// use lmrc_ssh::CommandOutput;
33 ///
34 /// let output = CommandOutput::new(
35 /// "Hello, World!".to_string(),
36 /// String::new(),
37 /// 0
38 /// );
39 /// assert_eq!(output.stdout, "Hello, World!");
40 /// assert!(output.is_success());
41 /// ```
42 pub fn new(stdout: String, stderr: String, exit_status: i32) -> Self {
43 Self {
44 stdout,
45 stderr,
46 exit_status,
47 }
48 }
49
50 /// Returns `true` if the command executed successfully (exit status 0).
51 ///
52 /// # Examples
53 ///
54 /// ```
55 /// use lmrc_ssh::CommandOutput;
56 ///
57 /// let success = CommandOutput::new("output".to_string(), String::new(), 0);
58 /// assert!(success.is_success());
59 ///
60 /// let failure = CommandOutput::new(String::new(), "error".to_string(), 1);
61 /// assert!(!failure.is_success());
62 /// ```
63 pub fn is_success(&self) -> bool {
64 self.exit_status == 0
65 }
66
67 /// Returns `true` if the command failed (non-zero exit status).
68 ///
69 /// # Examples
70 ///
71 /// ```
72 /// use lmrc_ssh::CommandOutput;
73 ///
74 /// let output = CommandOutput::new(String::new(), "error".to_string(), 1);
75 /// assert!(output.is_failure());
76 /// ```
77 pub fn is_failure(&self) -> bool {
78 !self.is_success()
79 }
80
81 /// Returns the combined output (stdout + stderr).
82 ///
83 /// # Examples
84 ///
85 /// ```
86 /// use lmrc_ssh::CommandOutput;
87 ///
88 /// let output = CommandOutput::new(
89 /// "line1\n".to_string(),
90 /// "error1\n".to_string(),
91 /// 0
92 /// );
93 /// assert_eq!(output.combined_output(), "line1\nerror1\n");
94 /// ```
95 pub fn combined_output(&self) -> String {
96 format!("{}{}", self.stdout, self.stderr)
97 }
98}
99
100impl std::fmt::Display for CommandOutput {
101 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
102 write!(
103 f,
104 "Exit Status: {}\nStdout:\n{}\nStderr:\n{}",
105 self.exit_status, self.stdout, self.stderr
106 )
107 }
108}
109
110#[cfg(test)]
111mod tests {
112 use super::*;
113
114 #[test]
115 fn test_new_output() {
116 let output = CommandOutput::new("test".to_string(), "err".to_string(), 0);
117 assert_eq!(output.stdout, "test");
118 assert_eq!(output.stderr, "err");
119 assert_eq!(output.exit_status, 0);
120 }
121
122 #[test]
123 fn test_is_success() {
124 let success = CommandOutput::new(String::new(), String::new(), 0);
125 assert!(success.is_success());
126 assert!(!success.is_failure());
127
128 let failure = CommandOutput::new(String::new(), String::new(), 1);
129 assert!(failure.is_failure());
130 assert!(!failure.is_success());
131 }
132
133 #[test]
134 fn test_combined_output() {
135 let output = CommandOutput::new("out\n".to_string(), "err\n".to_string(), 0);
136 assert_eq!(output.combined_output(), "out\nerr\n");
137 }
138
139 #[test]
140 fn test_display() {
141 let output = CommandOutput::new("stdout".to_string(), "stderr".to_string(), 0);
142 let display = format!("{}", output);
143 assert!(display.contains("Exit Status: 0"));
144 assert!(display.contains("stdout"));
145 assert!(display.contains("stderr"));
146 }
147}