Fix and improve test outputs for prop tests.
This commit is contained in:
parent
7a2537432a
commit
fbda31d980
|
@ -125,6 +125,12 @@ pub enum Error {
|
|||
|
||||
impl Error {
|
||||
pub fn report(&self) {
|
||||
if let Error::TestFailure { verbose, .. } = self {
|
||||
if !verbose {
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
println!("{self:?}")
|
||||
}
|
||||
|
||||
|
@ -320,25 +326,33 @@ impl Diagnostic for Error {
|
|||
Error::Parse { error, .. } => error.kind.help(),
|
||||
Error::Type { error, .. } => error.help(),
|
||||
Error::StandardIo(_) => None,
|
||||
Error::MissingManifest { .. } => Some(Box::new("Try running `aiken new <REPOSITORY/PROJECT>` to initialise a project with an example manifest.")),
|
||||
Error::MissingManifest { .. } => Some(Box::new(
|
||||
"Try running `aiken new <REPOSITORY/PROJECT>` to initialise a project with an example manifest.",
|
||||
)),
|
||||
Error::TomlLoading { .. } => None,
|
||||
Error::Format { .. } => None,
|
||||
Error::TestFailure { assertion, .. } => match assertion {
|
||||
None => None,
|
||||
Some(hint) => Some(Box::new(hint.to_string()))
|
||||
Some(hint) => Some(Box::new(hint.to_string())),
|
||||
},
|
||||
Error::Http(_) => None,
|
||||
Error::ZipExtract(_) => None,
|
||||
Error::JoinError(_) => None,
|
||||
Error::UnknownPackageVersion{..} => Some(Box::new("Perhaps, double-check the package repository and version?")),
|
||||
Error::UnableToResolvePackage{..} => Some(Box::new("The network is unavailable and the package isn't in the local cache either. Try connecting to the Internet so I can look it up?")),
|
||||
Error::UnknownPackageVersion { .. } => Some(Box::new(
|
||||
"Perhaps, double-check the package repository and version?",
|
||||
)),
|
||||
Error::UnableToResolvePackage { .. } => Some(Box::new(
|
||||
"The network is unavailable and the package isn't in the local cache either. Try connecting to the Internet so I can look it up?",
|
||||
)),
|
||||
Error::Json(error) => Some(Box::new(format!("{error}"))),
|
||||
Error::MalformedStakeAddress { error } => Some(Box::new(format!("A stake address must be provided either as a base16-encoded string, or as a bech32-encoded string with the 'stake' or 'stake_test' prefix.{hint}", hint = match error {
|
||||
Error::MalformedStakeAddress { error } => Some(Box::new(format!(
|
||||
"A stake address must be provided either as a base16-encoded string, or as a bech32-encoded string with the 'stake' or 'stake_test' prefix.{hint}",
|
||||
hint = match error {
|
||||
Some(error) => format!("\n\nHere's the error I encountered: {error}"),
|
||||
None => String::new(),
|
||||
}))),
|
||||
Error::NoValidatorNotFound { known_validators } => {
|
||||
Some(Box::new(format!(
|
||||
}
|
||||
))),
|
||||
Error::NoValidatorNotFound { known_validators } => Some(Box::new(format!(
|
||||
"Here's a list of all validators I've found in your project. Please double-check this list against the options that you've provided:\n\n{}",
|
||||
known_validators
|
||||
.iter()
|
||||
|
@ -348,10 +362,8 @@ impl Diagnostic for Error {
|
|||
))
|
||||
.collect::<Vec<String>>()
|
||||
.join("\n")
|
||||
)))
|
||||
},
|
||||
Error::MoreThanOneValidatorFound { known_validators } => {
|
||||
Some(Box::new(format!(
|
||||
))),
|
||||
Error::MoreThanOneValidatorFound { known_validators } => Some(Box::new(format!(
|
||||
"Here's a list of all validators I've found in your project. Select one of them using the appropriate options:\n\n{}",
|
||||
known_validators
|
||||
.iter()
|
||||
|
@ -361,8 +373,7 @@ impl Diagnostic for Error {
|
|||
))
|
||||
.collect::<Vec<String>>()
|
||||
.join("\n")
|
||||
)))
|
||||
},
|
||||
))),
|
||||
Error::Module(e) => e.help(),
|
||||
}
|
||||
}
|
||||
|
|
|
@ -10,11 +10,7 @@ pub fn ansi_len(s: &str) -> usize {
|
|||
pub fn len_longest_line(zero: usize, s: &str) -> usize {
|
||||
s.lines().fold(zero, |max, l| {
|
||||
let n = ansi_len(l);
|
||||
if n > max {
|
||||
n
|
||||
} else {
|
||||
max
|
||||
}
|
||||
if n > max { n } else { max }
|
||||
})
|
||||
}
|
||||
|
||||
|
@ -73,11 +69,18 @@ pub fn open_box(
|
|||
|
||||
let top = format!(
|
||||
"{} {}",
|
||||
border_style("┍━"),
|
||||
border_style(if footer.is_empty() {
|
||||
"┝━"
|
||||
} else {
|
||||
"┍━"
|
||||
}),
|
||||
pad_right(format!("{title} "), i - 1, &border_style("━")),
|
||||
);
|
||||
|
||||
let bottom = format!(
|
||||
let bottom = if footer.is_empty() {
|
||||
border_style("╽")
|
||||
} else {
|
||||
format!(
|
||||
"{} {}",
|
||||
pad_right(
|
||||
border_style("┕"),
|
||||
|
@ -85,7 +88,8 @@ pub fn open_box(
|
|||
&border_style("━")
|
||||
),
|
||||
footer
|
||||
);
|
||||
)
|
||||
};
|
||||
|
||||
format!("{top}\n{content}\n{bottom}")
|
||||
}
|
||||
|
@ -120,11 +124,7 @@ pub fn pad_right(mut text: String, n: usize, delimiter: &str) -> String {
|
|||
}
|
||||
|
||||
pub fn style_if(styled: bool, s: String, apply_style: fn(String) -> String) -> String {
|
||||
if styled {
|
||||
apply_style(s)
|
||||
} else {
|
||||
s
|
||||
}
|
||||
if styled { apply_style(s) } else { s }
|
||||
}
|
||||
|
||||
pub fn multiline(max_len: usize, s: String) -> Vec<String> {
|
||||
|
|
|
@ -1,5 +1,7 @@
|
|||
use crate::pretty;
|
||||
use crate::test_framework::{PropertyTestResult, TestResult, UnitTestResult};
|
||||
use crate::{
|
||||
pretty,
|
||||
test_framework::{PropertyTestResult, TestResult, UnitTestResult},
|
||||
};
|
||||
use aiken_lang::{expr::UntypedExpr, format::Formatter};
|
||||
use owo_colors::{OwoColorize, Stream::Stderr};
|
||||
use std::{collections::BTreeMap, fmt::Display, path::PathBuf};
|
||||
|
@ -169,7 +171,7 @@ impl EventListener for Terminal {
|
|||
);
|
||||
}
|
||||
Event::FinishedTests { tests } => {
|
||||
let (max_mem, max_cpu) = find_max_execution_units(&tests);
|
||||
let (max_mem, max_cpu, max_iter) = find_max_execution_units(&tests);
|
||||
|
||||
for (module, results) in &group_by_module(&tests) {
|
||||
let title = module
|
||||
|
@ -179,7 +181,7 @@ impl EventListener for Terminal {
|
|||
|
||||
let tests = results
|
||||
.iter()
|
||||
.map(|r| fmt_test(r, max_mem, max_cpu, true))
|
||||
.map(|r| fmt_test(r, max_mem, max_cpu, max_iter, true))
|
||||
.collect::<Vec<String>>()
|
||||
.join("\n");
|
||||
|
||||
|
@ -254,6 +256,7 @@ fn fmt_test(
|
|||
result: &TestResult<UntypedExpr>,
|
||||
max_mem: usize,
|
||||
max_cpu: usize,
|
||||
max_iter: usize,
|
||||
styled: bool,
|
||||
) -> String {
|
||||
// Status
|
||||
|
@ -292,10 +295,10 @@ fn fmt_test(
|
|||
test = pretty::pad_right(
|
||||
format!(
|
||||
"{test} [after {} test{}]",
|
||||
pretty::pad_left(iterations.to_string(), 3, " "),
|
||||
pretty::pad_left(iterations.to_string(), max_iter, " "),
|
||||
if *iterations > 1 { "s" } else { "" }
|
||||
),
|
||||
14 + max_mem + max_cpu,
|
||||
18 + max_mem + max_cpu + max_iter,
|
||||
" ",
|
||||
);
|
||||
}
|
||||
|
@ -317,7 +320,7 @@ fn fmt_test(
|
|||
{
|
||||
test = format!(
|
||||
"{test}\n{}",
|
||||
pretty::boxed_with(
|
||||
pretty::open_box(
|
||||
&pretty::style_if(styled, "counterexample".to_string(), |s| s
|
||||
.if_supports_color(Stderr, |s| s.red())
|
||||
.if_supports_color(Stderr, |s| s.bold())
|
||||
|
@ -325,6 +328,7 @@ fn fmt_test(
|
|||
&Formatter::new()
|
||||
.expr(counterexample, false)
|
||||
.to_pretty_string(70),
|
||||
"",
|
||||
|s| s.red().to_string()
|
||||
)
|
||||
)
|
||||
|
@ -392,23 +396,29 @@ fn group_by_module<T>(results: &Vec<TestResult<T>>) -> BTreeMap<String, Vec<&Tes
|
|||
modules
|
||||
}
|
||||
|
||||
fn find_max_execution_units<T>(xs: &[TestResult<T>]) -> (usize, usize) {
|
||||
let (max_mem, max_cpu) = xs
|
||||
.iter()
|
||||
.fold((0, 0), |(max_mem, max_cpu), test| match test {
|
||||
TestResult::PropertyTestResult(..) => (max_mem, max_cpu),
|
||||
fn find_max_execution_units<T>(xs: &[TestResult<T>]) -> (usize, usize, usize) {
|
||||
let (max_mem, max_cpu, max_iter) =
|
||||
xs.iter()
|
||||
.fold((0, 0, 0), |(max_mem, max_cpu, max_iter), test| match test {
|
||||
TestResult::PropertyTestResult(PropertyTestResult { iterations, .. }) => {
|
||||
(max_mem, max_cpu, std::cmp::max(max_iter, *iterations))
|
||||
}
|
||||
TestResult::UnitTestResult(UnitTestResult { spent_budget, .. }) => {
|
||||
if spent_budget.mem >= max_mem && spent_budget.cpu >= max_cpu {
|
||||
(spent_budget.mem, spent_budget.cpu)
|
||||
(spent_budget.mem, spent_budget.cpu, max_iter)
|
||||
} else if spent_budget.mem > max_mem {
|
||||
(spent_budget.mem, max_cpu)
|
||||
(spent_budget.mem, max_cpu, max_iter)
|
||||
} else if spent_budget.cpu > max_cpu {
|
||||
(max_mem, spent_budget.cpu)
|
||||
(max_mem, spent_budget.cpu, max_iter)
|
||||
} else {
|
||||
(max_mem, max_cpu)
|
||||
(max_mem, max_cpu, max_iter)
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
(max_mem.to_string().len(), max_cpu.to_string().len())
|
||||
(
|
||||
max_mem.to_string().len(),
|
||||
max_cpu.to_string().len(),
|
||||
max_iter.to_string().len(),
|
||||
)
|
||||
}
|
||||
|
|
|
@ -123,7 +123,9 @@ where
|
|||
|
||||
if errs.iter().any(|e| matches!(e, Error::TestFailure { .. })) {
|
||||
eprintln!(
|
||||
" ━━━━━━\n ╰─▶ use {} {} to replay",
|
||||
" {}══╤══\n{} ╰─▶ use {} {} to replay",
|
||||
if errs.len() > 1 { "═" } else { "" },
|
||||
if errs.len() > 1 { " " } else { "" },
|
||||
"--seed".if_supports_color(Stderr, |s| s.bold()),
|
||||
format!("{seed}").if_supports_color(Stderr, |s| s.bold())
|
||||
);
|
||||
|
|
Loading…
Reference in New Issue