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 { | impl Error { | ||||||
|     pub fn report(&self) { |     pub fn report(&self) { | ||||||
|  |         if let Error::TestFailure { verbose, .. } = self { | ||||||
|  |             if !verbose { | ||||||
|  |                 return; | ||||||
|  |             } | ||||||
|  |         } | ||||||
|  | 
 | ||||||
|         println!("{self:?}") |         println!("{self:?}") | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|  | @ -320,25 +326,33 @@ impl Diagnostic for Error { | ||||||
|             Error::Parse { error, .. } => error.kind.help(), |             Error::Parse { error, .. } => error.kind.help(), | ||||||
|             Error::Type { error, .. } => error.help(), |             Error::Type { error, .. } => error.help(), | ||||||
|             Error::StandardIo(_) => None, |             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::TomlLoading { .. } => None, | ||||||
|             Error::Format { .. } => None, |             Error::Format { .. } => None, | ||||||
|             Error::TestFailure { assertion, .. } => match assertion { |             Error::TestFailure { assertion, .. } => match assertion { | ||||||
|                 None => None, |                 None => None, | ||||||
|                 Some(hint) => Some(Box::new(hint.to_string())) |                 Some(hint) => Some(Box::new(hint.to_string())), | ||||||
|             }, |             }, | ||||||
|             Error::Http(_) => None, |             Error::Http(_) => None, | ||||||
|             Error::ZipExtract(_) => None, |             Error::ZipExtract(_) => None, | ||||||
|             Error::JoinError(_) => None, |             Error::JoinError(_) => None, | ||||||
|             Error::UnknownPackageVersion{..} => Some(Box::new("Perhaps, double-check the package repository and version?")), |             Error::UnknownPackageVersion { .. } => Some(Box::new( | ||||||
|             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?")), |                 "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::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}"), |                     Some(error) => format!("\n\nHere's the error I encountered: {error}"), | ||||||
|                     None => String::new(), |                     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{}", |                 "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 |                 known_validators | ||||||
|                     .iter() |                     .iter() | ||||||
|  | @ -348,10 +362,8 @@ impl Diagnostic for Error { | ||||||
|                     )) |                     )) | ||||||
|                     .collect::<Vec<String>>() |                     .collect::<Vec<String>>() | ||||||
|                     .join("\n") |                     .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{}", |                 "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 |                 known_validators | ||||||
|                     .iter() |                     .iter() | ||||||
|  | @ -361,8 +373,7 @@ impl Diagnostic for Error { | ||||||
|                     )) |                     )) | ||||||
|                     .collect::<Vec<String>>() |                     .collect::<Vec<String>>() | ||||||
|                     .join("\n") |                     .join("\n") | ||||||
|                 ))) |             ))), | ||||||
|             }, |  | ||||||
|             Error::Module(e) => e.help(), |             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 { | pub fn len_longest_line(zero: usize, s: &str) -> usize { | ||||||
|     s.lines().fold(zero, |max, l| { |     s.lines().fold(zero, |max, l| { | ||||||
|         let n = ansi_len(l); |         let n = ansi_len(l); | ||||||
|         if n > max { |         if n > max { n } else { max } | ||||||
|             n |  | ||||||
|         } else { |  | ||||||
|             max |  | ||||||
|         } |  | ||||||
|     }) |     }) | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
|  | @ -73,11 +69,18 @@ pub fn open_box( | ||||||
| 
 | 
 | ||||||
|     let top = format!( |     let top = format!( | ||||||
|         "{} {}", |         "{} {}", | ||||||
|         border_style("┍━"), |         border_style(if footer.is_empty() { | ||||||
|  |             "┝━" | ||||||
|  |         } else { | ||||||
|  |             "┍━" | ||||||
|  |         }), | ||||||
|         pad_right(format!("{title} "), i - 1, &border_style("━")), |         pad_right(format!("{title} "), i - 1, &border_style("━")), | ||||||
|     ); |     ); | ||||||
| 
 | 
 | ||||||
|     let bottom = format!( |     let bottom = if footer.is_empty() { | ||||||
|  |         border_style("╽") | ||||||
|  |     } else { | ||||||
|  |         format!( | ||||||
|             "{} {}", |             "{} {}", | ||||||
|             pad_right( |             pad_right( | ||||||
|                 border_style("┕"), |                 border_style("┕"), | ||||||
|  | @ -85,7 +88,8 @@ pub fn open_box( | ||||||
|                 &border_style("━") |                 &border_style("━") | ||||||
|             ), |             ), | ||||||
|             footer |             footer | ||||||
|     ); |         ) | ||||||
|  |     }; | ||||||
| 
 | 
 | ||||||
|     format!("{top}\n{content}\n{bottom}") |     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 { | pub fn style_if(styled: bool, s: String, apply_style: fn(String) -> String) -> String { | ||||||
|     if styled { |     if styled { apply_style(s) } else { s } | ||||||
|         apply_style(s) |  | ||||||
|     } else { |  | ||||||
|         s |  | ||||||
|     } |  | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| pub fn multiline(max_len: usize, s: String) -> Vec<String> { | pub fn multiline(max_len: usize, s: String) -> Vec<String> { | ||||||
|  |  | ||||||
|  | @ -1,5 +1,7 @@ | ||||||
| use crate::pretty; | use crate::{ | ||||||
| use crate::test_framework::{PropertyTestResult, TestResult, UnitTestResult}; |     pretty, | ||||||
|  |     test_framework::{PropertyTestResult, TestResult, UnitTestResult}, | ||||||
|  | }; | ||||||
| use aiken_lang::{expr::UntypedExpr, format::Formatter}; | use aiken_lang::{expr::UntypedExpr, format::Formatter}; | ||||||
| use owo_colors::{OwoColorize, Stream::Stderr}; | use owo_colors::{OwoColorize, Stream::Stderr}; | ||||||
| use std::{collections::BTreeMap, fmt::Display, path::PathBuf}; | use std::{collections::BTreeMap, fmt::Display, path::PathBuf}; | ||||||
|  | @ -169,7 +171,7 @@ impl EventListener for Terminal { | ||||||
|                 ); |                 ); | ||||||
|             } |             } | ||||||
|             Event::FinishedTests { tests } => { |             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) { |                 for (module, results) in &group_by_module(&tests) { | ||||||
|                     let title = module |                     let title = module | ||||||
|  | @ -179,7 +181,7 @@ impl EventListener for Terminal { | ||||||
| 
 | 
 | ||||||
|                     let tests = results |                     let tests = results | ||||||
|                         .iter() |                         .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>>() |                         .collect::<Vec<String>>() | ||||||
|                         .join("\n"); |                         .join("\n"); | ||||||
| 
 | 
 | ||||||
|  | @ -254,6 +256,7 @@ fn fmt_test( | ||||||
|     result: &TestResult<UntypedExpr>, |     result: &TestResult<UntypedExpr>, | ||||||
|     max_mem: usize, |     max_mem: usize, | ||||||
|     max_cpu: usize, |     max_cpu: usize, | ||||||
|  |     max_iter: usize, | ||||||
|     styled: bool, |     styled: bool, | ||||||
| ) -> String { | ) -> String { | ||||||
|     // Status
 |     // Status
 | ||||||
|  | @ -292,10 +295,10 @@ fn fmt_test( | ||||||
|             test = pretty::pad_right( |             test = pretty::pad_right( | ||||||
|                 format!( |                 format!( | ||||||
|                     "{test} [after {} test{}]", |                     "{test} [after {} test{}]", | ||||||
|                     pretty::pad_left(iterations.to_string(), 3, " "), |                     pretty::pad_left(iterations.to_string(), max_iter, " "), | ||||||
|                     if *iterations > 1 { "s" } else { "" } |                     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 = format!( | ||||||
|             "{test}\n{}", |             "{test}\n{}", | ||||||
|             pretty::boxed_with( |             pretty::open_box( | ||||||
|                 &pretty::style_if(styled, "counterexample".to_string(), |s| s |                 &pretty::style_if(styled, "counterexample".to_string(), |s| s | ||||||
|                     .if_supports_color(Stderr, |s| s.red()) |                     .if_supports_color(Stderr, |s| s.red()) | ||||||
|                     .if_supports_color(Stderr, |s| s.bold()) |                     .if_supports_color(Stderr, |s| s.bold()) | ||||||
|  | @ -325,6 +328,7 @@ fn fmt_test( | ||||||
|                 &Formatter::new() |                 &Formatter::new() | ||||||
|                     .expr(counterexample, false) |                     .expr(counterexample, false) | ||||||
|                     .to_pretty_string(70), |                     .to_pretty_string(70), | ||||||
|  |                 "", | ||||||
|                 |s| s.red().to_string() |                 |s| s.red().to_string() | ||||||
|             ) |             ) | ||||||
|         ) |         ) | ||||||
|  | @ -392,23 +396,29 @@ fn group_by_module<T>(results: &Vec<TestResult<T>>) -> BTreeMap<String, Vec<&Tes | ||||||
|     modules |     modules | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| fn find_max_execution_units<T>(xs: &[TestResult<T>]) -> (usize, usize) { | fn find_max_execution_units<T>(xs: &[TestResult<T>]) -> (usize, usize, usize) { | ||||||
|     let (max_mem, max_cpu) = xs |     let (max_mem, max_cpu, max_iter) = | ||||||
|         .iter() |         xs.iter() | ||||||
|         .fold((0, 0), |(max_mem, max_cpu), test| match test { |             .fold((0, 0, 0), |(max_mem, max_cpu, max_iter), test| match test { | ||||||
|             TestResult::PropertyTestResult(..) => (max_mem, max_cpu), |                 TestResult::PropertyTestResult(PropertyTestResult { iterations, .. }) => { | ||||||
|  |                     (max_mem, max_cpu, std::cmp::max(max_iter, *iterations)) | ||||||
|  |                 } | ||||||
|                 TestResult::UnitTestResult(UnitTestResult { spent_budget, .. }) => { |                 TestResult::UnitTestResult(UnitTestResult { spent_budget, .. }) => { | ||||||
|                     if spent_budget.mem >= max_mem && spent_budget.cpu >= max_cpu { |                     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 { |                     } 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 { |                     } else if spent_budget.cpu > max_cpu { | ||||||
|                     (max_mem, spent_budget.cpu) |                         (max_mem, spent_budget.cpu, max_iter) | ||||||
|                     } else { |                     } 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 { .. })) { |         if errs.iter().any(|e| matches!(e, Error::TestFailure { .. })) { | ||||||
|             eprintln!( |             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()), |                 "--seed".if_supports_color(Stderr, |s| s.bold()), | ||||||
|                 format!("{seed}").if_supports_color(Stderr, |s| s.bold()) |                 format!("{seed}").if_supports_color(Stderr, |s| s.bold()) | ||||||
|             ); |             ); | ||||||
|  |  | ||||||
		Loading…
	
		Reference in New Issue
	
	 KtorZ
						KtorZ