// 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, failure: Option, } #[derive(Clone, Copy)] pub enum ReportStyle { Short, Verbose, } impl TestResult { pub fn new(name: &str) -> TestResult { TestResult { name: name.to_string(), total_time: 0.0, n_elements: 0, failure: None, } } pub fn report(&self, style: ReportStyle) { let fail_string = match &self.failure { None => "pass".into(), Some(s) => format!("fail ({})", 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: String) { self.failure = Some(explanation); } 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) }