#[macro_export]
macro_rules! assert_all {
( $($cond:expr),+) => {
{
use std::collections::HashMap;
let mut errors: HashMap<usize, &str> = HashMap::new();
$(
let _ = match $cond {
true => {},
false => {
errors.insert(errors.len(), stringify!($cond));
}
};
)*
if !errors.is_empty() {
errors.iter().for_each(|(_, msg)| {
eprintln!("Assertion failed: {}", msg);
});
panic!("{} assertion(s) failed.", errors.len());
}
}
};
}
#[macro_export]
macro_rules! assert_all_match_result {
( $($cond:expr),+) => {
{
use std::collections::HashMap;
let mut errors: HashMap<usize, (&str, &str)> = HashMap::new();
$(
let _ = match $cond {
Ok(_) => {},
Err(e) => {
errors.insert(errors.len(), (stringify!($cond), e.to_string().leak()));
}
};
)*
if !errors.is_empty() {
errors.iter().for_each(|(_, (msg, error))| {
eprintln!("Assertion failed: {}. Error: {}", msg, error);
});
panic!("{} assertion(s) failed.", errors.len());
}
}
};
}
#[macro_export]
macro_rules! assert_match_option {
($current:expr) => {
assert_match_option!($current, "Assertion failed")
};
($current:expr, $msg:literal) => {
match $current {
Some(_) => Ok(()),
None => Err($msg)
}
};
}
#[macro_export]
macro_rules! assert_not_match_option {
($current:expr) => {
assert_not_match_option!($current, "Assertion failed")
};
($current:expr, $msg:literal) => {
match $current {
Some(_) => Err($msg),
None => Ok(())
}
};
}
#[macro_export]
macro_rules! assert_match_result {
($current:expr) => {
assert_match_result!($current, "Assertion failed")
};
($current:expr, $msg:literal) => {
match $current {
Ok(_) => Ok(()),
Err(_) => Err($msg)
}
};
}
#[macro_export]
macro_rules! assert_match_natural_result {
($current:expr) => {
match $current {
Ok(_) => Ok(()),
Err(e) => Err(e)
}
};
}
#[macro_export]
macro_rules! assert_not_match_result {
($current:expr) => {
assert_not_match_result!($current, "Assertion failed")
};
($current:expr, $msg:literal) => {
match $current {
Ok(_) => Err($msg),
Err(_) => Ok(())
}
};
}
#[macro_export]
macro_rules! assert_match_values {
($current:expr, $ok_value:pat, $nok_value:pat) => {
assert_match_values!($current, $ok_value, $nok_value, "Assertion failed")
};
($current:expr, $ok_value:pat, $nok_value:pat, $msg:literal) => {
assert!(
facility_match_values!($current, $ok_value, $nok_value).is_ok(),
$msg
);
};
}
#[macro_export]
macro_rules! assert_not_match_values {
($current:expr, $nok_value:pat, $ok_value:pat) => {
assert_not_match_values!($current, $nok_value, $ok_value, "Assertion failed")
};
($current:expr, $nok_value:pat, $ok_value:pat, $msg:literal) => {
assert!(
facility_match_values!($current, $nok_value, $ok_value).is_err(),
$msg
);
};
}
#[macro_export]
macro_rules! assert_none {
($value:expr) => {
assert_none!($value, "Assert none failure")
};
($value:expr, $msg:literal) => {
assert_eq!(None, $value, $msg)
};
}
#[macro_export]
macro_rules! assert_not_none {
($value:expr) => {
assert_not_none!($value, "Assertion not none failed")
};
($value:expr, $msg:literal) => {
assert_ne!(None, $value, $msg)
};
}
#[macro_export]
macro_rules! assert_slices_eq {
($awaiting:expr, $result:expr) => {
assert_slices_eq!($awaiting, $result, "Assertion failed");
};
($awaiting:expr, $result:expr, $msg:literal) => {{
assert_eq!($awaiting.len(), $result.len(), $msg);
let mut cpt = 0;
while cpt < $awaiting.len() {
assert_eq!($awaiting[cpt], $result[cpt], $msg);
cpt += 1;
}
}};
}
#[macro_export]
macro_rules! assert_slices_ne {
($awaiting:expr, $result:expr) => {
assert_slices_ne!($awaiting, $result, "Assertion failed");
};
($awaiting:expr, $result:expr, $msg:literal) => {{
let mut cpt = 0;
let min = match $awaiting.len() < $result.len() {
true => $awaiting.len(),
false => $result.len(),
};
while cpt < min && ($awaiting[cpt] == $result[cpt]) {
cpt += 1;
}
assert!(!((cpt == min) & ($awaiting.len() == $result.len())), $msg);
}};
}
#[macro_export]
macro_rules! assert_same_slices {
($awaiting:expr, $result:expr) => {
assert_same_slices!($awaiting, $result, "Assertion failed");
};
($awaiting:expr, $result:expr, $msg:literal) => {{
assert_eq!($awaiting.len(), $result.len(), $msg);
let mut cpt = 0;
let mut is_same = true;
while cpt < $awaiting.len() && is_same {
is_same = $result.iter().filter(|&x| *x == $awaiting[cpt]).count() != 0;
cpt += 1;
}
assert!(is_same, $msg);
}};
}
#[macro_export]
macro_rules! assert_not_same_slices {
($awaiting:expr, $result:expr) => {
assert_not_same_slices!($awaiting, $result, "Assertion failed")
};
($awaiting:expr, $result:expr, $msg:literal) => {{
let min = match $awaiting.len() < $result.len() {
true => $awaiting.len(),
false => $result.len(),
};
let mut common = 1;
let mut cpt = 0;
while cpt < min && common != 0 {
common = $result.iter().filter(|&x| *x == $awaiting[cpt]).count();
cpt += 1;
}
assert!((common == 0) | ($awaiting.len() != $result.len()), $msg);
}};
}
#[macro_export]
macro_rules! facility_match_values {
($current:expr, $ok_value:pat, $nok_value:pat) => {
facility_match_values!($current, $ok_value, $nok_value, "Assertion failed")
};
($current:expr, $ok_value:pat, $nok_value:pat, $msg:literal) => {
match $current {
$ok_value => Ok(()),
$nok_value => Err($msg),
}
};
}
#[macro_export]
macro_rules! fail {
() => {
fail!("Test failed")
};
($msg:literal) => {
panic!("{}", $msg)
};
}
#[macro_export]
macro_rules! repeat {
($nb:expr, $b:block) => {
let mut max: usize = $nb as usize;
while max != 0 {
{
$b
}
max -= 1;
}
};
}
#[macro_export]
macro_rules! setup {
($b:block) => {
$b
};
}
#[macro_export]
macro_rules! teardown {
($b:block) => {
struct AutoDown;
impl Drop for AutoDown {
fn drop(&mut self) {
$b
}
}
let _a = AutoDown;
};
}
#[cfg(test)]
mod test {
use std::fs;
use std::fs::File;
use std::path::Path;
#[test]
fn test_assert_all_true() {
assert_all!(true);
}
#[should_panic]
#[test]
fn test_assert_all_false_panic() {
assert_all!(false);
}
#[should_panic]
#[test]
fn test_assert_all_false_true_panic() {
assert_all!(false, true);
}
#[should_panic]
#[test]
fn test_assert_all_true_false_panic() {
assert_all!(true, false);
}
#[test]
fn test_assert_all_multi() {
assert_all!(true, 1 + 1 == 2);
}
#[should_panic]
#[test]
fn test_assert_all_multi_panic() {
assert_all!(true, 1 + 1 == 2, 1 * 2 == 6);
}
#[should_panic]
#[test]
fn test_assert_multi_long_panic() {
assert_all!(true, 1 + 1 == 2, 1 * 2 == 6, 0 * 0 == 0, 'a' == 'b');
}
#[should_panic]
#[test]
fn test_assert_all_compte_panic() {
assert_all!(compute(), 1 + 1 == 2, 1 * 2 == 6);
}
fn compute() -> bool {
false
}
#[test]
fn test_assert_all_match_result() {
assert_all_match_result!(result_ok1(), result_ok2())
}
fn result_ok1() -> Result<(), &'static str> {
Ok(())
}
fn result_ok2() -> Result<(), &'static str> {
Ok(())
}
#[should_panic]
#[test]
fn test_assert_all_match_result_fail() {
assert_all_match_result!(result_ok1(), result_fail1(), result_ok2(), result_fail2())
}
fn result_fail1() -> Result<(), &'static str> {
Err("result fail1")
}
fn result_fail2() -> Result<(), &'static str> {
Err("result fail2")
}
#[test]
fn test_assert_all_match_result_with_arguments() {
["value", "Value", "VALUE"].iter().for_each(|v| assert_all_match_result!(arg_with_value1(v), arg_with_value2(v)));
}
fn arg_with_value1(val: &str) -> Result<(), &'static str>{
match val.to_ascii_lowercase().as_str() {
"value" => Ok(()),
_ => Err("Invalid value")
}
}
fn arg_with_value2(val: &str) -> Result<(), &'static str>{
match val.to_ascii_lowercase().as_str() {
"value" => Ok(()),
_ => Err("Invalid value")
}
}
#[should_panic]
#[test]
fn test_assert_all_match_result_with_invalid_arguments() {
["value", "VALUE", "pas value"].iter().for_each(|v| assert_all_match_result!(arg_with_value1("value"), arg_with_value2(v)));
}
#[should_panic]
#[test]
fn test_fail() {
fail!();
}
#[test]
fn test_setup_teardown() {
setup!({
File::create(Path::new("test.txt")).unwrap();
});
teardown!({
fs::remove_file(Path::new("test.txt")).unwrap();
});
assert!(Path::new("test.txt").exists());
}
#[test]
fn test_setup_teardown_file_is_not_exist() {
assert!(!Path::new("test.txt").exists());
}
#[test]
fn test_assert_match_option() -> Result<(), &'static str> {
assert_match_option!(Some(5))
}
#[test]
fn test_assert_match_none() {
let result = assert_match_option!(None::<i32>);
assert_eq!(result, Err("Assertion failed"));
}
#[test]
fn test_assert_match_with_specific_error_message() {
let result = assert_match_option!(None::<i32>, "It's failed");
assert_eq!(result, Err("It's failed"));
}
#[test]
fn test_assert_not_match_option() {
let result = assert_not_match_option!(None::<i32>);
assert_eq!(result, Ok(()));
}
#[test]
fn test_assert_not_match_not_none() {
let result = assert_not_match_option!(Some(5));
assert_eq!(result, Err("Assertion failed"));
}
#[test]
fn test_assert_not_match_none_with_message() {
let result = assert_not_match_option!(Some("Foo"), "Foo failed");
assert_eq!(result, Err("Foo failed"));
}
#[test]
fn test_assert_match_result() -> Result<(), &'static str> {
assert_match_result!(Ok::<i32, &str>(5))
}
#[test]
fn test_assert_match_result_with_message() {
let result = assert_match_result!(Err::<(), &str>("Foo"), "It's failed");
assert_eq!(result, Err("It's failed"));
}
#[test]
fn test_assert_match_natural_result() -> Result<(), &'static str> {
assert_match_natural_result!(match_natural_result(true))
}
fn match_natural_result(must_ok: bool) -> Result<&'static str, &'static str> {
match must_ok {
true => Ok("Ok"),
false => Err("Error value")
}
}
#[test]
fn test_assert_match_natural_result_with_failed() {
assert!(assert_match_natural_result!(match_natural_result(false)).is_err());
}
#[test]
fn test_assert_match_natural_result_other_type() -> Result<(),i32> {
assert_match_natural_result!(match_result_with_i32(true))
}
fn match_result_with_i32(must_ok: bool) -> Result<(), i32> {
match must_ok {
true => Ok(()),
false => Err(1)
}
}
#[test]
fn test_assert_match_natural_result_other_type_failed() {
assert!(assert_match_natural_result!(match_result_with_i32(false)).is_err());
}
#[test]
fn test_assert_not_match_result() -> Result<(), &'static str> {
assert_not_match_result!(Err::<(), i32>(5), "It's failed")
}
#[test]
fn test_assert_none_with_method() {
assert_none!(none_method());
}
fn none_method() -> Option<i32> {
None
}
#[should_panic]
#[test]
fn test_assert_none_with_none() {
assert_none!(Some(3));
}
#[test]
fn test_assert_not_none_valid() {
assert_not_none!(Some(1));
}
#[should_panic]
#[test]
fn test_assert_not_none_from_method() {
assert_not_none!(none_method());
}
#[test]
fn test_assert_slices_eq() {
let slice1 = [1, 2, 3, 4, 5];
let slice2 = [1, 2, 3, 4, 5];
assert_slices_eq!(slice1, slice2);
}
#[should_panic]
#[test]
fn test_assert_slices_eq_not_same_size() {
let slice1 = ['a', 'b', 'c', 'd'];
let slice2 = ['a', 'b', 'c'];
assert_slices_eq!(slice1, slice2);
}
#[should_panic]
#[test]
fn test_assert_slices_eq_not_equal() {
let slice1 = [1, 2, 3, 4, 5];
let slice2 = [1, 2, 3, 5, 4];
assert_slices_eq!(slice1, slice2);
}
#[test]
fn test_assert_slices_eq_direct() {
assert_slices_eq!([1, 2, 3, 4, 5], [1, 2, 3, 4, 5]);
}
#[test]
fn test_assert_slices_eq_with_vector() {
let vec1 = vec![1, 2, 3, 4, 5];
let vec2 = vec![1, 2, 3, 4, 5];
assert_slices_eq!(vec1, vec2);
}
#[test]
fn test_assert_slices_eq_with_string() {
assert_slices_eq!("abcdef".as_bytes(), "abcdef".as_bytes());
}
#[should_panic]
#[test]
fn test_assert_slices_eq_with_message() {
assert_slices_eq!([1, 2, 3, 4], [1, 2, 3, 3], "Error with this test");
}
#[test]
fn test_assert_slices_ne_not_same_content() {
assert_slices_ne!([1, 2, 3, 4, 5], [1, 2, 3, 4, 0]);
}
#[test]
fn test_assert_slices_ne_not_same_size() {
assert_slices_ne!([1, 2, 3, 4], [1, 2, 3]);
}
#[test]
fn test_assert_slices_ne_not_same_size_reversed() {
assert_slices_ne!([1, 2, 3], [1, 2, 3, 4]);
}
#[should_panic]
#[test]
fn test_assert_slices_ne_same_slices() {
assert_slices_ne!([1, 2, 3, 4], [1, 2, 3, 4]);
}
#[should_panic]
#[test]
fn test_assert_slices_ne_with_message() {
assert_slices_ne!([1, 2, 3, 4], [1, 2, 3, 4], "Slices are not valids");
}
#[test]
fn test_assert_match_values() {
assert_match_values!(true, true, false);
}
#[should_panic]
#[test]
fn test_assert_match_values_not_match() {
assert_match_values!(false, true, false);
}
#[test]
fn test_assert_not_match_values() {
assert_not_match_values!(true, false, true);
}
#[should_panic]
#[test]
fn test_assert_not_match_values_not_match() {
assert_not_match_values!(true, true, false);
}
#[test]
fn test_assert_match_values_with_chars() {
assert_match_values!('a', 'a'..'z', _);
}
#[test]
fn test_assert_not_match_values_with_chars() {
assert_not_match_values!(' ', 'a'..'z', _);
}
#[test]
fn test_assert_same_slices_same_order_and_size() {
assert_same_slices!([1, 2, 4, 5], [1, 2, 4, 5]);
}
#[test]
fn test_assert_same_slices_same_reverse_order() {
assert_same_slices!([1, 2, 3, 4, 5], [5, 4, 3, 2, 1]);
}
#[should_panic]
#[test]
fn test_assert_same_slices_same_order_not_size() {
assert_same_slices!([1, 2, 3, 4], [1, 2, 3, 4, 5]);
}
#[should_panic]
#[test]
fn test_assert_same_slices_same_reverse_order_and_size() {
assert_same_slices!([5, 4, 3, 2, 1], [5, 4, 3]);
}
#[test]
fn test_assert_same_slices_same_vector() {
let v1 = vec!['a', 'b', 'c', 'd'];
let v2 = vec!['d', 'c', 'b', 'a'];
assert_same_slices!(v1, v2);
}
#[should_panic]
#[test]
fn test_assert_same_slices_same_message() {
let v1 = vec!['a', 'b', 'c', 'd'];
let v2 = vec!['e', 'f', 'b', 'a'];
assert_same_slices!(v1, v2, "Slices are not the same");
}
#[test]
fn test_assert_not_same_slices_same_size() {
assert_not_same_slices!([1, 2, 3, 4, 5], [6, 7, 8, 9, 10]);
}
#[test]
fn test_assert_not_same_slices_not_same_size() {
assert_not_same_slices!([1, 2, 3], [1, 2, 3, 4]);
}
#[should_panic]
#[test]
fn test_assert_not_same_slices_with_same_slices() {
assert_not_same_slices!([1, 2, 3, 4, 5], [1, 2, 3, 4, 5]);
}
#[test]
fn test_assert_not_same_slices_same_size_not_same_content() {
assert_not_same_slices!([1, 2, 3, 4, 5], [1, 2, 3, 4, 4]);
}
#[test]
fn test_repeat_10_repeats() {
let mut counter = 0;
repeat!(10, {
counter += 1;
});
assert_eq!(10, counter);
}
#[test]
fn test_repeat_zero_repeat() {
let mut counter = 1;
repeat!(0, {
counter += 1;
});
assert_eq!(1, counter);
}
}