#![allow(unused_macros)] #![allow(unused_imports)] use multisql::Glue; #[derive(Debug)] pub(crate) struct Test { pub test: fn(Glue), pub name: &'static str, } macro_rules! testcase { ($test: expr) => { inventory::submit!(Test { test: $test, name: module_path!(), }); }; } pub(crate) use testcase; macro_rules! run { ($test: expr, $storage: expr) => { use { indicatif::{ProgressBar, ProgressStyle}, std::panic::catch_unwind, }; let progress = ProgressBar::new_spinner().with_message( $test .name .strip_prefix(concat!(module_path!(), "::")) .unwrap(), ); progress.set_style( ProgressStyle::default_spinner() .template("\t[Running]\t{msg:.yellow} {spinner}") .tick_chars("|/—\\*"), ); progress.enable_steady_tick(100); // progress.tick(); // Aesthetic -- in case too fast match catch_unwind(|| ($test.test)($storage($test.name))) { Ok(_) => { progress.set_style( ProgressStyle::default_spinner().template("\t[Passed]\t{msg:.green}"), ); progress.finish(); } Err(err) => { progress.set_style( ProgressStyle::default_spinner().template("\t[Failed]\t{msg:.red} {spinner}"), ); progress.finish(); panic!("Test Failed; Error: {:?}", err); } } }; } pub(crate) use run; macro_rules! announce { ($content: expr) => { println!("-<\t{}", $content) }; } pub(crate) use announce; macro_rules! announce_test_suite { () => { announce!(format!("[Suite]\t\t{}", module_path!())) }; } pub(crate) use announce_test_suite; macro_rules! make_basic_table { ($glue: expr) => { $glue .execute( r#" CREATE TABLE basic ( a INTEGER ) "#, ) .expect("CREATE TABLE basic"); $glue .execute( r#" INSERT INTO basic ( a ) VALUES ( 1 ) "#, ) .expect("INSERT basic"); }; } pub(crate) use make_basic_table; macro_rules! rows { (($($type: ident),*) : ($($value: expr),*), $(($($value_todo: expr),*)),+) => {{ let mut first = rows!( ($($type),*): ($($value),*) ); first.append( &mut rows!( ($($type),*): $(($($value_todo),*)),* ) ); first // Icky but works... is there a better way? }}; (($($type: ident),*) : ($($value: expr),*)) => { vec![multisql::Row(vec![$(multisql::Value::$type($value)),*])] }; (($($_type: ident),*) :) => { vec![] }; } pub(crate) use rows; macro_rules! select { ($($label: tt = $type: ident),* : $(($($value: expr),*)),*) => ({ multisql::Payload::Select { labels: vec![$( stringify!($label).to_owned().replace("\"", "")),+], rows: rows!(($($type),*) : $(($($value.into()),*)),*) } }); ($($label: tt = $type: ident),* : _) => ({ // Crappy but working way of testing single NULL multisql::Payload::Select { labels: vec![$( stringify!($label).to_owned().replace("\"", "")),+], rows: vec![multisql::Row(vec![multisql::Value::Null])] } }); } pub(crate) use select; macro_rules! execute { ($storage: expr, $query: expr) => {{ $storage .execute($query) .expect(&format!("Query Failed: {query}", query = $query)); }}; } pub(crate) use execute; macro_rules! assert_select { ($storage: expr, $query: expr => $($label: tt = $type: ident),* : $(($($value: expr),*)),*) => {{ if let ( Ok(multisql::Payload::Select { labels, mut rows }), multisql::Payload::Select { labels: expect_labels, rows: expect_rows } ) = ( $storage.execute($query), select!($($label = $type),* : $(($($value),*)),*) ) { use fstrings::*; assert_eq!(labels, expect_labels); expect_rows.iter().for_each(|expect_row| {rows.remove(rows.iter().position(|row| expect_row == row).expect(&f!("\nRow missing: {expect_row:?}.\nQuery: {query}\nOther rows: {rows:?}", query=$query)));}); rows.is_empty().then(||()).expect(&f!("Unexpected rows: {rows:?}\nQuery: {query}", query=$query)); } else { let _result = $storage.execute($query); let _expect = select!($($label = $type),* : $(($($value),*)),*); panic!("SELECT Error\n\tQuery:\n\t{query}\n\tResult:\n\t{result:?}\n\tExpected:\t{expect:?}", query=$query, result=_result, expect=_expect); } }}; ($storage: expr, $query: expr => $($label: tt = $type: ident),* : $((_)),*) => {{ // Crappy but working way of testing single NULL if let ( Ok(multisql::Payload::Select { labels, mut rows }), multisql::Payload::Select { labels: expect_labels, rows: expect_rows } ) = ( $storage.execute($query), select!($($label = $type),* : _) ) { use fstrings::*; assert_eq!(labels, expect_labels); expect_rows.iter().for_each(|expect_row| {rows.remove(rows.iter().position(|_row| matches!(expect_row, _row)).expect(&f!("\nRow missing: {expect_row:?}.\nQuery: {query}\nOther rows: {rows:?}", query=$query)));}); rows.is_empty().then(||()).expect(&f!("Unexpected rows: {rows:?}\nQuery: {query}", query=$query)); } else { let _result = $storage.execute($query); let _expect = select!($($label = $type),* : _); panic!("SELECT Error\n\tQuery:\n\t{query}\n\tResult:\n\t{result:?}\n\tExpected:\t{expect:?}", query=$query, result=_result, expect=_expect); } }}; } pub(crate) use assert_select; macro_rules! assert_error { ($storage: expr, $query: expr, $error: expr) => {{ let _test: Result<(), _> = Err($error); matches!($storage.execute($query), _test) .then(|| ()) .expect(&format!( "Unexpected\n\tQuery:\n\t{query}\n\tExpected:\t{expect:?}", query = $query, expect = _test )); }}; ($storage: expr, $query: expr) => { $storage.execute($query).expect_err(&format!( "Unexpected Success\n\tQuery:\n\t{query}\n\tResult", query = $query )); }; } pub(crate) use assert_error; macro_rules! assert_success { ($storage: expr, $query: expr, $success: expr) => {{ let _test: multisql::Result<_> = Ok($success); matches!($storage.execute($query), _test) .then(|| ()) .expect(&format!( "Unexpected\n\tQuery:\n\t{query}\n\tExpected:\t{expect:?}", query = $query, expect = $success )); }}; ($storage: expr, $query: expr) => { $storage.execute($query).expect(&format!( "Unexpected Error\n\tQuery:\n\t{query}\n\tResult", query = $query )); }; } pub(crate) use assert_success; macro_rules! assert_result { ($storage: expr, $query: expr, $success: expr) => {{ let _test: multisql::Result = $success; assert!(matches!($storage.execute($query), _test)); }}; } pub(crate) use assert_result; macro_rules! assert_select_count { ($storage: expr, $query: expr, $count: expr) => {{ if let Ok(multisql::Payload::Select { rows, .. }) = $storage.execute($query) { assert_eq!(rows.len(), $count) } else { panic!( "Assert Select Count Failed\n\tQuery: {query}\n\tExpected: {count}", query = $query, count = $count ) } }}; } pub(crate) use assert_select_count;