meli/utilities: add print utilities for tests

Add:

- eprint_step_fn():  Returns a closure that prints a formatted message,
  without a trailing newline, and prefixed with an increasing counter.
- eprintln_ok_fn(): Returns a closure that prints the string " OK\n" to
  `stderr` with optional color formatting.

Signed-off-by: Manos Pitsidianakis <manos@pitsidianak.is>
This commit is contained in:
Manos Pitsidianakis 2024-11-28 10:39:47 +02:00
parent efab99fda2
commit 03df2ac128
No known key found for this signature in database
GPG key ID: 7729C7707F7E09D0
3 changed files with 98 additions and 22 deletions

View file

@ -32,6 +32,7 @@ use sealed_test::prelude::*;
use tempfile::TempDir;
use super::*;
use crate::utilities::tests::{eprint_step_fn, eprintln_ok_fn};
#[test]
fn test_sqlite3_query_to_sql() {
@ -104,6 +105,14 @@ fn test_sqlite3_reindex() {
const ACCOUNT_NAME: &str = "test";
const DB_FILE_SHOULD_EXIST_ERR_MSG: &str = "A db file should now exist, after indexing.";
let eprintln_ok = eprintln_ok_fn();
let mut eprint_step_closure = eprint_step_fn();
macro_rules! eprint_step {
($($arg:tt)+) => {{
eprint_step_closure(format_args!($($arg)+));
}};
}
/// Helper functions
mod helpers {
use super::*;
@ -181,7 +190,7 @@ fn test_sqlite3_reindex() {
let temp_dir = TempDir::new().unwrap();
print!("Sanitize environment...");
eprint_step!("Sanitize environment...");
for var in [
"PAGER",
"MANPATH",
@ -204,8 +213,8 @@ fn test_sqlite3_reindex() {
temp_dir.path().join(".local").join(".share"),
);
println!(" OK");
print!("Create maildir backend we will use for the sqlite3 index database...");
eprintln_ok();
eprint_step!("Create maildir backend we will use for the sqlite3 index database...");
let backend_event_queue = Arc::new(Mutex::new(VecDeque::with_capacity(16)));
let backend_event_consumer = {
@ -221,8 +230,8 @@ fn test_sqlite3_reindex() {
let acc_name = Arc::<str>::from(maildir.account_name.to_string());
let collection = melib::Collection::default();
println!(" OK");
print!(
eprintln_ok();
eprint_step!(
"Confirm the root mailbox was created by fetching all mailboxes and inspecting their \
contents..."
);
@ -246,8 +255,8 @@ fn test_sqlite3_reindex() {
assert_eq!(mailbox.special_usage(), SpecialUsageMailbox::Normal);
assert_eq!(mailbox.count().unwrap(), (0, 0));
println!(" OK");
print!("Insert actual email into our backend...");
eprintln_ok();
eprint_step!("Insert actual email into our backend...");
macro_rules! batch_entry {
($path:literal) => {
@ -265,8 +274,8 @@ fn test_sqlite3_reindex() {
batch_entry!("../../../melib/tests/data/git-am-breakage-with-MIME-decoding.mbox.gz"),
];
println!(" OK");
print!(
eprintln_ok();
eprint_step!(
"Perform a save operation for {} emails...",
mail_batch.len()
);
@ -280,8 +289,8 @@ fn test_sqlite3_reindex() {
.collect::<Result<Vec<()>>>()
.unwrap();
println!(" OK");
print!(
eprintln_ok();
eprint_step!(
"Perform a manual refresh operation, since we have not spawned any watcher threads with \
`MailBackend::watch` (we do not need to)..."
);
@ -311,8 +320,8 @@ fn test_sqlite3_reindex() {
}
}
println!(" OK");
print!("Backend setup over, we're now finally ready to test sqlite3 indexing...");
eprintln_ok();
eprint_step!("Backend setup over, we're now finally ready to test sqlite3 indexing...");
let backend_mutex = Arc::new(RwLock::new(maildir as Box<dyn MailBackend>));
assert_eq!(
@ -345,8 +354,8 @@ fn test_sqlite3_reindex() {
);
assert_eq!(list_xdg_data_home_dir_entries(), vec![db_path.clone()],);
println!(" OK");
print!("Ensure re-indexing for a second time does not trigger any errors...");
eprintln_ok();
eprint_step!("Ensure re-indexing for a second time does not trigger any errors...");
perform_reindex(
Arc::clone(&acc_name),
collection.clone(),
@ -358,8 +367,8 @@ fn test_sqlite3_reindex() {
assert_eq!(db_path, db_path_2);
assert_eq!(list_xdg_data_home_dir_entries(), vec![db_path],);
println!(" OK");
print!("Search for all envelopes, as a smoke test...");
eprintln_ok();
eprint_step!("Search for all envelopes, as a smoke test...");
let search_results = perform_search(&acc_name, Query::Body(String::new()));
assert_eq!(
search_results.len(),
@ -375,8 +384,8 @@ fn test_sqlite3_reindex() {
.collect::<HashSet<EnvelopeHash>>(),
*collection.get_mailbox(root_mailbox_hash)
);
println!(" OK");
print!(
eprintln_ok();
eprint_step!(
"Search for torvalds as a submitter, since he sent all those patches we inserted into the \
backend. So this should return all envelopes as well..."
);
@ -393,8 +402,8 @@ fn test_sqlite3_reindex() {
.collect::<HashSet<EnvelopeHash>>(),
);
println!(" OK");
print!("Search for only specific recipients, which should not return all envelopes...");
eprintln_ok();
eprint_step!("Search for only specific recipients, which should not return all envelopes...");
let search_results = perform_search(&acc_name, Query::To("marc.stevens@cwi.nl".into()));
assert_eq!(
search_results.len(),
@ -415,4 +424,5 @@ fn test_sqlite3_reindex() {
.map(|env| env.hash())
.collect::<HashSet<EnvelopeHash>>()
);
eprintln_ok();
}

View file

@ -45,7 +45,7 @@ mod tables;
pub use self::tables::*;
#[cfg(test)]
mod tests;
pub mod tests;
pub type AutoCompleteFn = Box<dyn Fn(&Context, &str) -> Vec<AutoCompleteEntry> + Send + Sync>;

View file

@ -176,3 +176,69 @@ fn test_utilities_text_input_field() {
assert_eq!(field.as_str(), EMOJIGRAM);
_ = tmpdir.close();
}
/// Returns a closure that prints the string " OK\n" to `stderr`.
///
/// If `stderr` is a TTY, the output will contain escape code sequences to
/// change the foreground color of the text with the second indexed color
/// (usually green).
pub fn eprintln_ok_fn() -> Box<dyn Fn()> {
if crate::terminal::is_tty() && std::env::var_os("NO_COLOR").is_none() {
struct SetAf2(String);
struct Sgr0(String);
fn get_tput_sequences() -> Option<(SetAf2, Sgr0)> {
use std::process::{Command, Stdio};
let setaf_2 = SetAf2(
String::from_utf8(
Command::new("tput")
.args(["setaf", "2"])
.stdout(Stdio::piped())
.stdin(Stdio::null())
.stderr(Stdio::inherit())
.output()
.ok()?
.stdout,
)
.ok()?,
);
let sgr0 = Sgr0(
String::from_utf8(
Command::new("tput")
.arg("sgr0")
.stdout(Stdio::piped())
.stdin(Stdio::null())
.stderr(Stdio::inherit())
.output()
.ok()?
.stdout,
)
.ok()?,
);
Some((setaf_2, sgr0))
}
if let Some((SetAf2(setaf_2), Sgr0(sgr0))) = get_tput_sequences() {
return Box::new(move || {
eprintln!(" {setaf_2}OK{sgr0}");
});
}
}
Box::new(|| {
eprintln!(" OK");
})
}
/// Returns a closure that prints a formatted message, without a trailing
/// newline, and prefixed with an increasing counter.
pub fn eprint_step_fn() -> Box<dyn FnMut(std::fmt::Arguments) -> usize> {
let mut counter = 1;
Box::new(move |args: std::fmt::Arguments| {
let step = counter;
eprint!("{step}. {}", args);
counter += 1;
step
})
}