blob: d83761f86878013a420949fd61d00ca4888e83e1 [file] [log] [blame]
// Copyright 2019 The Fuchsia Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
use {crate::act::ActionResults, std::fmt};
pub struct ActionResultFormatter<'a> {
action_results: &'a ActionResults,
}
impl<'a> fmt::Display for ActionResultFormatter<'a> {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
self.write_text(f)
}
}
impl<'a> ActionResultFormatter<'a> {
pub fn new(action_results: &ActionResults) -> ActionResultFormatter<'_> {
ActionResultFormatter { action_results }
}
fn write_text(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
Self::write_section(f, "Errors", &self.action_results.errors, true)?;
Self::write_section(
f,
"Featured Values",
&self.action_results.gauges,
self.action_results.sort_gauges,
)?;
Self::write_section(f, "Warnings", &self.action_results.warnings, true)?;
self.write_plugins(f)?;
if self.action_results.verbose {
Self::write_section(
f,
"Featured Values (Not Computable)",
&self.action_results.broken_gauges,
true,
)?;
Self::write_section(f, "Info", &self.action_results.infos, true)?;
}
Ok(())
}
fn write_section(
f: &mut fmt::Formatter<'_>,
label: &str,
lines: &Vec<String>,
sort: bool,
) -> fmt::Result {
if lines.is_empty() {
return Ok(());
}
Self::write_underlined(f, label)?;
let mut sorted_lines;
let output_lines = if sort {
sorted_lines = lines.clone();
sorted_lines.sort();
&sorted_lines
} else {
&lines
};
for line in output_lines {
writeln!(f, "{line}")?;
}
writeln!(f)
}
fn write_underlined(f: &mut fmt::Formatter<'_>, content: &str) -> fmt::Result {
writeln!(f, "{content}")?;
writeln!(f, "{}", "-".repeat(content.len()))
}
fn write_plugins(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
for (name, result) in &self.action_results.sub_results {
if !self.action_results.verbose
&& result.gauges.is_empty()
&& result.errors.is_empty()
&& result.warnings.is_empty()
{
writeln!(f, "Plugin '{name}' - nothing to show\n")?;
continue;
}
writeln!(f, "Plugin '{name}'")?;
// TODO(https://fxbug.dev/42076794): use self.verbose flag correctly in plugins.
ActionResultFormatter::new(&result).write_text(f)?;
}
Ok(())
}
}
#[cfg(test)]
mod test {
use super::*;
#[fuchsia::test]
fn action_result_formatter_to_warnings_when_no_actions_triggered() {
let action_results = ActionResults::new();
let formatter = ActionResultFormatter::new(&action_results);
assert_eq!(String::from(""), formatter.to_string());
}
#[fuchsia::test]
fn action_result_formatter_to_text_when_actions_triggered() {
let warnings = String::from(
"\
Warnings
--------
w1
w2
",
);
let mut action_results = ActionResults::new();
action_results.warnings.push(String::from("w1"));
action_results.warnings.push(String::from("w2"));
let formatter = ActionResultFormatter::new(&action_results);
assert_eq!(warnings, formatter.to_string());
}
#[fuchsia::test]
fn action_result_formatter_to_text_with_gauges() {
let warnings = String::from(
"\
Featured Values
---------------
g1
Warnings
--------
w1
w2
",
);
let mut action_results = ActionResults::new();
action_results.warnings.push(String::from("w1"));
action_results.warnings.push(String::from("w2"));
action_results.gauges.push(String::from("g1"));
let formatter = ActionResultFormatter::new(&action_results);
assert_eq!(warnings, formatter.to_string());
}
#[fuchsia::test]
fn action_result_formatter_sorts_output() {
let warnings = String::from(
"\
Featured Values
---------------
g1
g2
Warnings
--------
w1
w2
Plugin 'Crashes' - nothing to show
Plugin 'Warning'
Warnings
--------
w1
w2
Plugin 'Gauges'
Featured Values
---------------
g2
g1
",
);
{
let mut action_results = ActionResults::new();
action_results.warnings.push(String::from("w1"));
action_results.warnings.push(String::from("w2"));
action_results.gauges.push(String::from("g1"));
action_results.gauges.push(String::from("g2"));
let mut warnings_plugin = ActionResults::new();
warnings_plugin.warnings.push(String::from("w1"));
warnings_plugin.warnings.push(String::from("w2"));
let mut gauges_plugin = ActionResults::new();
gauges_plugin.gauges.push(String::from("g2"));
gauges_plugin.gauges.push(String::from("g1"));
gauges_plugin.sort_gauges = false;
action_results
.sub_results
.push(("Crashes".to_string(), Box::new(ActionResults::new())));
action_results.sub_results.push(("Warning".to_string(), Box::new(warnings_plugin)));
action_results.sub_results.push(("Gauges".to_string(), Box::new(gauges_plugin)));
let formatter = ActionResultFormatter::new(&action_results);
assert_eq!(warnings, formatter.to_string());
}
// Same as before, but reversed to test sorting.
{
let mut action_results = ActionResults::new();
action_results.warnings.push(String::from("w2"));
action_results.warnings.push(String::from("w1"));
action_results.gauges.push(String::from("g2"));
action_results.gauges.push(String::from("g1"));
let mut warnings_plugin = ActionResults::new();
warnings_plugin.warnings.push(String::from("w2"));
warnings_plugin.warnings.push(String::from("w1"));
let mut gauges_plugin = ActionResults::new();
gauges_plugin.gauges.push(String::from("g2"));
gauges_plugin.gauges.push(String::from("g1"));
gauges_plugin.sort_gauges = false;
action_results
.sub_results
.push(("Crashes".to_string(), Box::new(ActionResults::new())));
action_results.sub_results.push(("Warning".to_string(), Box::new(warnings_plugin)));
action_results.sub_results.push(("Gauges".to_string(), Box::new(gauges_plugin)));
let formatter = ActionResultFormatter::new(&action_results);
assert_eq!(warnings, formatter.to_string());
}
}
#[fuchsia::test]
fn action_result_verbose_works() {
let readable_warnings = String::from(
"\
Featured Values
---------------
g1: 42
Warnings
--------
w1
",
);
let verbose_warnings = format!(
"{}{}",
readable_warnings,
"\
Featured Values (Not Computable)
--------------------------------
g2: N/A
Info
----
i1
"
);
let mut action_results = ActionResults::new();
action_results.warnings.push(String::from("w1"));
action_results.gauges.push(String::from("g1: 42"));
action_results.infos.push(String::from("i1"));
action_results.broken_gauges.push(String::from("g2: N/A"));
let mut verbose_action_results = action_results.clone();
verbose_action_results.verbose = true;
assert_eq!(readable_warnings, ActionResultFormatter::new(&action_results).to_string());
assert_eq!(
verbose_warnings,
ActionResultFormatter::new(&verbose_action_results).to_string()
);
}
}