use std::time::Duration;
#[derive(Debug, Clone, PartialEq, Eq)]
pub struct Element(String, Value);
#[derive(Debug, Clone, PartialEq, Eq)]
pub struct Elements(Vec<Element>);
fn display_element(output: &mut String, indent: usize, element: &Element) {
let Element(k, v) = element;
for _ in 0..indent {
output.push(' ');
}
output.push_str(&k);
output.push_str(": ");
match v {
Value::Tree(tree) => {
output.push_str("\n");
for el in tree.0.iter() {
display_element(output, indent + 2, el)
}
}
Value::Str(s) => {
output.push_str(s);
output.push_str("\n");
}
}
}
impl Default for Elements {
fn default() -> Self {
Elements(Vec::new())
}
}
impl Elements {
pub fn new() -> Self {
Elements(Vec::new())
}
pub fn append(&mut self, key: &str, value: Value) {
self.0.push(Element::new(key, value))
}
pub fn display(&self, indent: usize) -> String {
let mut output = String::new();
for element in self.0.iter() {
display_element(&mut output, indent, element)
}
output
}
}
impl Element {
pub fn new(key: &str, v: Value) -> Self {
Element(key.to_string(), v)
}
pub fn display(&self, indent: usize) -> String {
let mut output = String::new();
display_element(&mut output, indent, self);
output
}
}
impl std::fmt::Display for Elements {
fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
write!(f, "{}", self.display(0))
}
}
#[derive(Debug, Clone, PartialEq, Eq)]
pub enum Value {
Str(String),
Tree(Elements),
}
impl Value {
pub fn sub(element: Element) -> Self {
Value::Tree(Elements(vec![element]))
}
}
impl From<&str> for Value {
fn from(s: &str) -> Self {
Value::Str(s.to_string())
}
}
impl From<String> for Value {
fn from(s: String) -> Self {
Value::Str(s)
}
}
impl From<Elements> for Value {
fn from(elements: Elements) -> Self {
Value::Tree(elements)
}
}
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub enum TestRunStatus {
Passed,
Failed,
Skipped,
}
#[derive(Debug, Clone, PartialEq, Eq, Default)]
pub struct TestResults {
pub nb_tests: usize,
pub nb_success: usize,
pub nb_failed: usize,
pub nb_skipped: usize,
pub failures: Vec<String>,
pub duration: Duration,
}
impl TestResults {
pub fn to_status(&self) -> TestRunStatus {
if self.nb_tests == 0 {
TestRunStatus::Skipped
} else if self.nb_failed > 0 {
TestRunStatus::Failed
} else if self.nb_skipped == self.nb_tests {
TestRunStatus::Skipped
} else {
TestRunStatus::Passed
}
}
pub fn new() -> Self {
Self::default()
}
pub fn add_success(&mut self) {
self.nb_tests += 1;
self.nb_success += 1;
}
pub fn add_failed(&mut self, reason: String) {
self.nb_tests += 1;
self.nb_failed += 1;
self.failures.push(reason);
}
pub fn set_duration(&mut self, d: Duration) {
self.duration = d
}
pub fn add_subtests(&mut self, sub_tests: &Self) {
self.nb_tests += sub_tests.nb_tests;
self.nb_success += sub_tests.nb_success;
self.nb_failed += sub_tests.nb_failed;
self.nb_skipped += sub_tests.nb_skipped;
self.failures.extend_from_slice(&sub_tests.failures);
self.duration += sub_tests.duration;
}
}