fuchsia_triage/
result_format.rs
1use crate::act::ActionResults;
6use std::fmt;
7
8pub struct ActionResultFormatter<'a> {
9 action_results: &'a ActionResults,
10}
11
12impl fmt::Display for ActionResultFormatter<'_> {
13 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
14 self.write_text(f)
15 }
16}
17
18impl ActionResultFormatter<'_> {
19 pub fn new(action_results: &ActionResults) -> ActionResultFormatter<'_> {
20 ActionResultFormatter { action_results }
21 }
22
23 fn write_text(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
24 Self::write_section(f, "Errors", &self.action_results.errors, true)?;
25 Self::write_section(
26 f,
27 "Featured Values",
28 &self.action_results.gauges,
29 self.action_results.sort_gauges,
30 )?;
31 Self::write_section(f, "Warnings", &self.action_results.warnings, true)?;
32 self.write_plugins(f)?;
33 if self.action_results.verbose {
34 Self::write_section(
35 f,
36 "Featured Values (Not Computable)",
37 &self.action_results.broken_gauges,
38 true,
39 )?;
40 Self::write_section(f, "Info", &self.action_results.infos, true)?;
41 }
42 Ok(())
43 }
44
45 fn write_section(
46 f: &mut fmt::Formatter<'_>,
47 label: &str,
48 lines: &Vec<String>,
49 sort: bool,
50 ) -> fmt::Result {
51 if lines.is_empty() {
52 return Ok(());
53 }
54
55 Self::write_underlined(f, label)?;
56 let mut sorted_lines;
57 let output_lines = if sort {
58 sorted_lines = lines.clone();
59 sorted_lines.sort();
60 &sorted_lines
61 } else {
62 lines
63 };
64 for line in output_lines {
65 writeln!(f, "{line}")?;
66 }
67 writeln!(f)
68 }
69
70 fn write_underlined(f: &mut fmt::Formatter<'_>, content: &str) -> fmt::Result {
71 writeln!(f, "{content}")?;
72 writeln!(f, "{}", "-".repeat(content.len()))
73 }
74
75 fn write_plugins(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
76 for (name, result) in &self.action_results.sub_results {
77 if !self.action_results.verbose
78 && result.gauges.is_empty()
79 && result.errors.is_empty()
80 && result.warnings.is_empty()
81 {
82 writeln!(f, "Plugin '{name}' - nothing to show\n")?;
83 continue;
84 }
85 writeln!(f, "Plugin '{name}'")?;
86 ActionResultFormatter::new(result).write_text(f)?;
88 }
89 Ok(())
90 }
91}
92
93#[cfg(test)]
94mod test {
95 use super::*;
96
97 #[fuchsia::test]
98 fn action_result_formatter_to_warnings_when_no_actions_triggered() {
99 let action_results = ActionResults::new();
100 let formatter = ActionResultFormatter::new(&action_results);
101
102 assert_eq!(String::from(""), formatter.to_string());
103 }
104
105 #[fuchsia::test]
106 fn action_result_formatter_to_text_when_actions_triggered() {
107 let warnings = String::from(
108 "\
109Warnings
110--------
111w1
112w2
113
114",
115 );
116
117 let mut action_results = ActionResults::new();
118 action_results.warnings.push(String::from("w1"));
119 action_results.warnings.push(String::from("w2"));
120
121 let formatter = ActionResultFormatter::new(&action_results);
122
123 assert_eq!(warnings, formatter.to_string());
124 }
125
126 #[fuchsia::test]
127 fn action_result_formatter_to_text_with_gauges() {
128 let warnings = String::from(
129 "\
130Featured Values
131---------------
132g1
133
134Warnings
135--------
136w1
137w2
138
139",
140 );
141
142 let mut action_results = ActionResults::new();
143 action_results.warnings.push(String::from("w1"));
144 action_results.warnings.push(String::from("w2"));
145 action_results.gauges.push(String::from("g1"));
146
147 let formatter = ActionResultFormatter::new(&action_results);
148
149 assert_eq!(warnings, formatter.to_string());
150 }
151
152 #[fuchsia::test]
153 fn action_result_formatter_sorts_output() {
154 let warnings = String::from(
155 "\
156Featured Values
157---------------
158g1
159g2
160
161Warnings
162--------
163w1
164w2
165
166Plugin 'Crashes' - nothing to show
167
168Plugin 'Warning'
169Warnings
170--------
171w1
172w2
173
174Plugin 'Gauges'
175Featured Values
176---------------
177g2
178g1
179
180",
181 );
182
183 {
184 let mut action_results = ActionResults::new();
185 action_results.warnings.push(String::from("w1"));
186 action_results.warnings.push(String::from("w2"));
187 action_results.gauges.push(String::from("g1"));
188 action_results.gauges.push(String::from("g2"));
189 let mut warnings_plugin = ActionResults::new();
190 warnings_plugin.warnings.push(String::from("w1"));
191 warnings_plugin.warnings.push(String::from("w2"));
192 let mut gauges_plugin = ActionResults::new();
193 gauges_plugin.gauges.push(String::from("g2"));
194 gauges_plugin.gauges.push(String::from("g1"));
195 gauges_plugin.sort_gauges = false;
196 action_results
197 .sub_results
198 .push(("Crashes".to_string(), Box::new(ActionResults::new())));
199 action_results.sub_results.push(("Warning".to_string(), Box::new(warnings_plugin)));
200 action_results.sub_results.push(("Gauges".to_string(), Box::new(gauges_plugin)));
201
202 let formatter = ActionResultFormatter::new(&action_results);
203
204 assert_eq!(warnings, formatter.to_string());
205 }
206
207 {
209 let mut action_results = ActionResults::new();
210 action_results.warnings.push(String::from("w2"));
211 action_results.warnings.push(String::from("w1"));
212 action_results.gauges.push(String::from("g2"));
213 action_results.gauges.push(String::from("g1"));
214 let mut warnings_plugin = ActionResults::new();
215 warnings_plugin.warnings.push(String::from("w2"));
216 warnings_plugin.warnings.push(String::from("w1"));
217 let mut gauges_plugin = ActionResults::new();
218 gauges_plugin.gauges.push(String::from("g2"));
219 gauges_plugin.gauges.push(String::from("g1"));
220 gauges_plugin.sort_gauges = false;
221 action_results
222 .sub_results
223 .push(("Crashes".to_string(), Box::new(ActionResults::new())));
224 action_results.sub_results.push(("Warning".to_string(), Box::new(warnings_plugin)));
225 action_results.sub_results.push(("Gauges".to_string(), Box::new(gauges_plugin)));
226
227 let formatter = ActionResultFormatter::new(&action_results);
228
229 assert_eq!(warnings, formatter.to_string());
230 }
231 }
232
233 #[fuchsia::test]
234 fn action_result_verbose_works() {
235 let readable_warnings = String::from(
236 "\
237Featured Values
238---------------
239g1: 42
240
241Warnings
242--------
243w1
244
245",
246 );
247 let verbose_warnings = format!(
248 "{}{}",
249 readable_warnings,
250 "\
251Featured Values (Not Computable)
252--------------------------------
253g2: N/A
254
255Info
256----
257i1
258
259"
260 );
261 let mut action_results = ActionResults::new();
262 action_results.warnings.push(String::from("w1"));
263 action_results.gauges.push(String::from("g1: 42"));
264 action_results.infos.push(String::from("i1"));
265 action_results.broken_gauges.push(String::from("g2: N/A"));
266 let mut verbose_action_results = action_results.clone();
267 verbose_action_results.verbose = true;
268 assert_eq!(readable_warnings, ActionResultFormatter::new(&action_results).to_string());
269 assert_eq!(
270 verbose_warnings,
271 ActionResultFormatter::new(&verbose_action_results).to_string()
272 );
273 }
274}