vello/tests/src/test_result.rs

124 lines
3.8 KiB
Rust
Raw Normal View History

// Copyright 2021 The piet-gpu authors.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// https://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
//
// Also licensed under MIT license, at your choice.
//! Recording of results from tests.
pub struct TestResult {
name: String,
// TODO: statistics. We're lean and mean for now.
total_time: f64,
n_elements: u64,
status: Status,
}
pub enum Status {
Pass,
Fail(String),
#[allow(unused)]
Skipped(String),
}
#[derive(Clone, Copy, PartialEq, Eq)]
pub enum ReportStyle {
Short,
Verbose,
}
impl TestResult {
pub fn new(name: impl Into<String>) -> TestResult {
TestResult {
name: name.into(),
total_time: 0.0,
n_elements: 0,
status: Status::Pass,
}
}
pub fn report(&self, style: ReportStyle) {
let fail_string = match &self.status {
Status::Pass => "pass".into(),
Status::Fail(s) => format!("fail ({})", s),
Status::Skipped(s) => format!("skipped ({})", s),
};
match style {
ReportStyle::Short => {
let mut timing_string = String::new();
if self.total_time > 0.0 {
if self.n_elements > 0 {
let throughput = self.n_elements as f64 / self.total_time;
timing_string = format!(" {} elements/s", format_nice(throughput, 1));
} else {
timing_string = format!(" {}s", format_nice(self.total_time, 1));
}
}
println!("{}: {}{}", self.name, fail_string, timing_string)
}
ReportStyle::Verbose => {
println!("test {}", self.name);
println!(" {}", fail_string);
if self.total_time > 0.0 {
println!(" {}s total time", format_nice(self.total_time, 1));
if self.n_elements > 0 {
println!(" {} elements", self.n_elements);
let throughput = self.n_elements as f64 / self.total_time;
println!(" {} elements/s", format_nice(throughput, 1));
}
}
}
}
}
pub fn fail(&mut self, explanation: impl Into<String>) {
self.status = Status::Fail(explanation.into());
}
#[allow(unused)]
pub fn skip(&mut self, explanation: impl Into<String>) {
self.status = Status::Skipped(explanation.into());
}
pub fn timing(&mut self, total_time: f64, n_elements: u64) {
self.total_time = total_time;
self.n_elements = n_elements;
}
}
fn format_nice(x: f64, precision: usize) -> String {
// Precision should probably scale; later
let (scale, suffix) = if x >= 1e12 && x < 1e15 {
(1e-12, "T")
} else if x >= 1e9 {
(1e-9, "G")
} else if x >= 1e6 {
(1e-6, "M")
} else if x >= 1e3 {
(1e-3, "k")
} else if x >= 1.0 {
(1.0, "")
} else if x >= 1e-3 {
(1e3, "m")
} else if x >= 1e-6 {
(1e6, "\u{00b5}")
} else if x >= 1e-9 {
(1e9, "n")
} else if x >= 1e-12 {
(1e12, "p")
} else {
return format!("{:.*e}", precision, x);
};
format!("{:.*}{}", precision, scale * x, suffix)
}