Merge pull request #166 from aiken-lang/some-interesting-test-cases
Include generics to get test cases working
This commit is contained in:
@@ -11,6 +11,10 @@ pub struct Args {
|
||||
#[clap(short, long)]
|
||||
skip_tests: bool,
|
||||
|
||||
/// When enabled, also pretty-print test UPLC on failure
|
||||
#[clap(long)]
|
||||
debug: bool,
|
||||
|
||||
/// Only run tests if their path + name match the given string
|
||||
#[clap(short, long)]
|
||||
match_tests: Option<String>,
|
||||
@@ -20,8 +24,11 @@ pub fn exec(
|
||||
Args {
|
||||
directory,
|
||||
skip_tests,
|
||||
debug,
|
||||
match_tests,
|
||||
}: Args,
|
||||
) -> miette::Result<()> {
|
||||
crate::with_project(directory, |p| p.check(skip_tests, match_tests.clone()))
|
||||
crate::with_project(directory, |p| {
|
||||
p.check(skip_tests, match_tests.clone(), debug)
|
||||
})
|
||||
}
|
||||
|
||||
@@ -1,10 +1,7 @@
|
||||
use std::{env, path::PathBuf};
|
||||
use std::collections::BTreeMap;
|
||||
use std::{env, path::PathBuf, process};
|
||||
|
||||
use aiken_project::{
|
||||
config::Config,
|
||||
telemetry::{self, TestInfo},
|
||||
Project,
|
||||
};
|
||||
use aiken_project::{config::Config, pretty, script::EvalInfo, telemetry, Project};
|
||||
use miette::IntoDiagnostic;
|
||||
use owo_colors::OwoColorize;
|
||||
use uplc::machine::cost_model::ExBudget;
|
||||
@@ -35,12 +32,20 @@ where
|
||||
|
||||
if let Err(err) = build_result {
|
||||
err.report();
|
||||
|
||||
miette::bail!("Failed: {} error(s), {warning_count} warning(s)", err.len(),);
|
||||
};
|
||||
|
||||
println!("\nFinished with {warning_count} warning(s)\n");
|
||||
|
||||
println!("{}", "Summary".purple().bold());
|
||||
println!(
|
||||
" {} error(s), {}",
|
||||
err.len(),
|
||||
format!("{warning_count} warning(s)").yellow(),
|
||||
);
|
||||
process::exit(1);
|
||||
} else {
|
||||
println!("{}", "Summary".purple().bold());
|
||||
println!(
|
||||
" 0 error, {}",
|
||||
format!("{warning_count} warning(s)").yellow(),
|
||||
);
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
|
||||
@@ -76,89 +81,149 @@ impl telemetry::EventListener for Terminal {
|
||||
output_path.to_str().unwrap_or("").bright_blue()
|
||||
);
|
||||
}
|
||||
telemetry::Event::EvaluatingFunction { results } => {
|
||||
println!("{}\n", "...Evaluating function".bold().purple());
|
||||
|
||||
let (max_mem, max_cpu) = find_max_execution_units(&results);
|
||||
|
||||
for eval_info in &results {
|
||||
println!(" {}", fmt_eval(eval_info, max_mem, max_cpu))
|
||||
}
|
||||
}
|
||||
telemetry::Event::RunningTests => {
|
||||
println!("{}\n", "...Running tests".bold().purple());
|
||||
}
|
||||
telemetry::Event::FinishedTests { tests } => {
|
||||
let (max_mem, max_cpu) = tests.iter().fold(
|
||||
(0, 0),
|
||||
|(max_mem, max_cpu), TestInfo { spent_budget, .. }| {
|
||||
if spent_budget.mem >= max_mem && spent_budget.cpu >= max_cpu {
|
||||
(spent_budget.mem, spent_budget.cpu)
|
||||
} else if spent_budget.mem > max_mem {
|
||||
(spent_budget.mem, max_cpu)
|
||||
} else if spent_budget.cpu > max_cpu {
|
||||
(max_mem, spent_budget.cpu)
|
||||
} else {
|
||||
(max_mem, max_cpu)
|
||||
}
|
||||
},
|
||||
);
|
||||
let (max_mem, max_cpu) = find_max_execution_units(&tests);
|
||||
|
||||
let max_mem = max_mem.to_string().len() as i32;
|
||||
let max_cpu = max_cpu.to_string().len() as i32;
|
||||
|
||||
for test_info in &tests {
|
||||
println!("{}", fmt_test(test_info, max_mem, max_cpu))
|
||||
for (module, infos) in &group_by_module(&tests) {
|
||||
let first = fmt_test(infos.first().unwrap(), max_mem, max_cpu, false).len();
|
||||
println!(
|
||||
"{} {} {}",
|
||||
" ┌──".bright_black(),
|
||||
module.bold().blue(),
|
||||
pretty::pad_left("".to_string(), first - module.len() - 3, "─")
|
||||
.bright_black()
|
||||
);
|
||||
for eval_info in infos {
|
||||
println!(
|
||||
" {} {}",
|
||||
"│".bright_black(),
|
||||
fmt_test(eval_info, max_mem, max_cpu, true)
|
||||
)
|
||||
}
|
||||
let last = fmt_test(infos.last().unwrap(), max_mem, max_cpu, false).len();
|
||||
let summary = fmt_test_summary(infos, false).len();
|
||||
println!(
|
||||
"{} {}\n",
|
||||
pretty::pad_right(" └".to_string(), last - summary + 5, "─")
|
||||
.bright_black(),
|
||||
fmt_test_summary(infos, true),
|
||||
);
|
||||
}
|
||||
|
||||
let (n_passed, n_failed) =
|
||||
tests
|
||||
.iter()
|
||||
.fold((0, 0), |(n_passed, n_failed), test_info| {
|
||||
if test_info.is_passing {
|
||||
(n_passed + 1, n_failed)
|
||||
} else {
|
||||
(n_passed, n_failed + 1)
|
||||
}
|
||||
});
|
||||
|
||||
println!(
|
||||
"{}",
|
||||
format!(
|
||||
"\n Summary: {} test(s), {}; {}.",
|
||||
tests.len(),
|
||||
format!("{} passed", n_passed).bright_green(),
|
||||
format!("{} failed", n_failed).bright_red()
|
||||
)
|
||||
.bold()
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn fmt_test(test_info: &TestInfo, max_mem: i32, max_cpu: i32) -> String {
|
||||
let TestInfo {
|
||||
is_passing,
|
||||
test,
|
||||
fn fmt_test(eval_info: &EvalInfo, max_mem: usize, max_cpu: usize, styled: bool) -> String {
|
||||
let EvalInfo {
|
||||
success,
|
||||
script,
|
||||
spent_budget,
|
||||
} = test_info;
|
||||
..
|
||||
} = eval_info;
|
||||
|
||||
let ExBudget { mem, cpu } = spent_budget;
|
||||
let mem_pad = pretty::pad_left(mem.to_string(), max_mem, " ");
|
||||
let cpu_pad = pretty::pad_left(cpu.to_string(), max_cpu, " ");
|
||||
|
||||
format!(
|
||||
"{} [mem: {}, cpu: {}] {}",
|
||||
if *success {
|
||||
pretty::style_if(styled, "PASS".to_string(), |s| s.bold().green().to_string())
|
||||
} else {
|
||||
pretty::style_if(styled, "FAIL".to_string(), |s| s.bold().red().to_string())
|
||||
},
|
||||
pretty::style_if(styled, mem_pad, |s| s.bright_white().to_string()),
|
||||
pretty::style_if(styled, cpu_pad, |s| s.bright_white().to_string()),
|
||||
pretty::style_if(styled, script.name.clone(), |s| s.bright_blue().to_string()),
|
||||
)
|
||||
}
|
||||
|
||||
fn fmt_test_summary(tests: &Vec<&EvalInfo>, styled: bool) -> String {
|
||||
let (n_passed, n_failed) = tests
|
||||
.iter()
|
||||
.fold((0, 0), |(n_passed, n_failed), test_info| {
|
||||
if test_info.success {
|
||||
(n_passed + 1, n_failed)
|
||||
} else {
|
||||
(n_passed, n_failed + 1)
|
||||
}
|
||||
});
|
||||
format!(
|
||||
"{} | {} | {}",
|
||||
pretty::style_if(styled, format!("{} tests", tests.len()), |s| s
|
||||
.bold()
|
||||
.to_string()),
|
||||
pretty::style_if(styled, format!("{} passed", n_passed), |s| s
|
||||
.bright_green()
|
||||
.bold()
|
||||
.to_string()),
|
||||
pretty::style_if(styled, format!("{} failed", n_failed), |s| s
|
||||
.bright_red()
|
||||
.bold()
|
||||
.to_string()),
|
||||
)
|
||||
}
|
||||
|
||||
fn fmt_eval(eval_info: &EvalInfo, max_mem: usize, max_cpu: usize) -> String {
|
||||
let EvalInfo {
|
||||
output,
|
||||
script,
|
||||
spent_budget,
|
||||
..
|
||||
} = eval_info;
|
||||
|
||||
let ExBudget { mem, cpu } = spent_budget;
|
||||
|
||||
format!(
|
||||
" [{}] [mem: {}, cpu: {}] {}::{}",
|
||||
if *is_passing {
|
||||
"PASS".bold().green().to_string()
|
||||
} else {
|
||||
"FAIL".bold().red().to_string()
|
||||
},
|
||||
pad_left(mem.to_string(), max_mem, " "),
|
||||
pad_left(cpu.to_string(), max_cpu, " "),
|
||||
test.module.blue(),
|
||||
test.name.bright_blue()
|
||||
" {}::{} [mem: {}, cpu: {}]\n │\n ╰─▶ {}",
|
||||
script.module.blue(),
|
||||
script.name.bright_blue(),
|
||||
pretty::pad_left(mem.to_string(), max_mem, " "),
|
||||
pretty::pad_left(cpu.to_string(), max_cpu, " "),
|
||||
output
|
||||
.as_ref()
|
||||
.map(|x| format!("{}", x))
|
||||
.unwrap_or_else(|| "Error.".to_string()),
|
||||
)
|
||||
}
|
||||
|
||||
fn pad_left(mut text: String, n: i32, delimiter: &str) -> String {
|
||||
let diff = n - text.len() as i32;
|
||||
|
||||
if diff.is_positive() {
|
||||
for _ in 0..diff {
|
||||
text.insert_str(0, delimiter);
|
||||
}
|
||||
fn group_by_module(infos: &Vec<EvalInfo>) -> BTreeMap<String, Vec<&EvalInfo>> {
|
||||
let mut modules = BTreeMap::new();
|
||||
for eval_info in infos {
|
||||
let xs: &mut Vec<&EvalInfo> = modules.entry(eval_info.script.module.clone()).or_default();
|
||||
xs.push(eval_info);
|
||||
}
|
||||
|
||||
text
|
||||
modules
|
||||
}
|
||||
|
||||
fn find_max_execution_units(xs: &[EvalInfo]) -> (usize, usize) {
|
||||
let (max_mem, max_cpu) = xs.iter().fold(
|
||||
(0, 0),
|
||||
|(max_mem, max_cpu), EvalInfo { spent_budget, .. }| {
|
||||
if spent_budget.mem >= max_mem && spent_budget.cpu >= max_cpu {
|
||||
(spent_budget.mem, spent_budget.cpu)
|
||||
} else if spent_budget.mem > max_mem {
|
||||
(spent_budget.mem, max_cpu)
|
||||
} else if spent_budget.cpu > max_cpu {
|
||||
(max_mem, spent_budget.cpu)
|
||||
} else {
|
||||
(max_mem, max_cpu)
|
||||
}
|
||||
},
|
||||
);
|
||||
|
||||
(max_mem.to_string().len(), max_cpu.to_string().len())
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user