diff --git a/code/rust/src/lib.rs b/code/rust/src/lib.rs index d731263..c51b9b9 100644 --- a/code/rust/src/lib.rs +++ b/code/rust/src/lib.rs @@ -1,3 +1,5 @@ +pub mod rules; + pub mod core; pub mod stacks; pub mod graphs; diff --git a/code/rust/src/rules/assert.rs b/code/rust/src/rules/assert.rs new file mode 100644 index 0000000..3a17a40 --- /dev/null +++ b/code/rust/src/rules/assert.rs @@ -0,0 +1,185 @@ +// ---------------------------------------------------------------- +// IMPORTS +// ---------------------------------------------------------------- + +// + +// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// Assert macros - length +// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +#[macro_export] +macro_rules! assert_length{ + ($a:expr, $b:expr $(, $message:expr)?)=>{ + assert_eq!($a.len(), $b $(, $message)?); + }; +} + +#[macro_export] +macro_rules! assert_length_ne{ + ($a:expr, $b:expr $(, $message:expr)?)=>{ + assert_ne!($a.len(), $b $(, $message)?); + }; +} + +#[macro_export] +macro_rules! assert_length_lt{ + ($a:expr, $b:expr $(, $message:expr)?)=>{ + assert!($a.len() < $b $(, $message)?); + }; +} + +#[macro_export] +macro_rules! assert_length_le{ + ($a:expr, $b:expr $(, $message:expr)?)=>{ + assert!($a.len() <= $b $(, $message)?); + }; +} + +#[macro_export] +macro_rules! assert_length_gt{ + ($a:expr, $b:expr $(, $message:expr)?)=>{ + assert!($a.len() > $b $(, $message)?); + }; +} + +#[macro_export] +macro_rules! assert_length_ge{ + ($a:expr, $b:expr $(, $message:expr)?)=>{ + assert!($a.len() >= $b $(, $message)?); + }; +} + +// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// Assert macros - length of sets +// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +#[macro_export] +macro_rules! assert_length_unique{ + ($a:expr, $b:expr $(, $message:expr)?)=>{ + { + use ads2::core::utils::vec_to_set; + assert_eq!(vec_to_set(&$a).len(), $b $(, $message)?); + } + }; +} + +#[macro_export] +macro_rules! assert_length_unique_ne{ + ($a:expr, $b:expr $(, $message:expr)?)=>{ + { + use ads2::core::utils::vec_to_set; + assert_ne!(vec_to_set(&$a).len(), $b $(, $message)?); + } + }; +} + +#[macro_export] +macro_rules! assert_length_unique_lt{ + ($a:expr, $b:expr $(, $message:expr)?)=>{ + { + use ads2::core::utils::vec_to_set; + assert!(vec_to_set(&$a).len() < $b $(, $message)?); + } + }; +} + + +#[macro_export] +macro_rules! assert_length_unique_le{ + ($a:expr, $b:expr $(, $message:expr)?)=>{ + { + use ads2::core::utils::vec_to_set; + assert!(vec_to_set(&$a).len() <= $b $(, $message)?); + } + }; +} + +#[macro_export] +macro_rules! assert_length_unique_gt{ + ($a:expr, $b:expr $(, $message:expr)?)=>{ + { + use ads2::core::utils::vec_to_set; + assert!(vec_to_set(&$a).len() > $b $(, $message)?); + } + }; +} + +#[macro_export] +macro_rules! assert_length_unique_ge{ + ($a:expr, $b:expr $(, $message:expr)?)=>{ + { + use ads2::core::utils::vec_to_set; + assert!(vec_to_set(&$a).len() >= $b $(, $message)?); + } + }; +} + +// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// Assert macros - contains +// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +#[macro_export] +macro_rules! assert_contains{ + ($a:expr, $b:expr $(, $message:expr)?)=>{ + assert!($a.contains(&$b) $(, $message)?); + }; +} + +#[macro_export] +macro_rules! assert_not_contains{ + ($a:expr, $b:expr $(, $message:expr)?)=>{ + assert!(!$a.contains(&$b) $(, $message)?); + }; +} + +// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// Assert macros - equality of sets +// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +#[macro_export] +macro_rules! assert_eq_contents{ + ($a:expr, $b:expr $(, $message:expr)?)=>{ + { + use ads2::core::utils::vec_to_set; + assert_eq!(vec_to_set(&$a), vec_to_set(&$b) $(, $message)?); + } + }; +} + +#[macro_export] +macro_rules! assert_ne_contents{ + ($a:expr, $b:expr $(, $message:expr)?)=>{ + { + use ads2::core::utils::vec_to_set; + assert_ne!(vec_to_set(&$a), vec_to_set(&$b)); + } + }; +} + +#[macro_export] +macro_rules! assert_subset{ + ($a:expr, $b:expr $(, $message:expr)?)=>{ + { + for element in $a.clone() { + assert!($b.contains(&element) $(, $message)?); + } + } + }; +} + +#[macro_export] +macro_rules! assert_not_subset{ + ($a:expr, $b:expr $(, $message:expr)?)=>{ + { + let mut found = false; + for element in $a.clone() { + if !($b.contains(&element)) { + found = true; + break; + } + } + assert!(found $(, $message)?); + } + }; +} diff --git a/code/rust/src/rules/mod.rs b/code/rust/src/rules/mod.rs new file mode 100644 index 0000000..0897e2a --- /dev/null +++ b/code/rust/src/rules/mod.rs @@ -0,0 +1 @@ +pub mod assert; diff --git a/code/rust/tests/mod.rs b/code/rust/tests/mod.rs index 9e6933e..da7823e 100644 --- a/code/rust/tests/mod.rs +++ b/code/rust/tests/mod.rs @@ -2,5 +2,6 @@ extern crate ads2; extern crate rstest; pub mod test_core; -pub mod test_stacks; pub mod test_graphs; +pub mod test_rules; +pub mod test_stacks; diff --git a/code/rust/tests/test_rules/mod.rs b/code/rust/tests/test_rules/mod.rs new file mode 100644 index 0000000..29e2dfe --- /dev/null +++ b/code/rust/tests/test_rules/mod.rs @@ -0,0 +1 @@ +pub mod test_assert; diff --git a/code/rust/tests/test_rules/test_assert.rs b/code/rust/tests/test_rules/test_assert.rs new file mode 100644 index 0000000..c578ba6 --- /dev/null +++ b/code/rust/tests/test_rules/test_assert.rs @@ -0,0 +1,432 @@ +// ---------------------------------------------------------------- +// IMPORTS +// ---------------------------------------------------------------- + +use rstest::fixture; +use rstest::rstest; +use std::fmt::Debug; +use std::hash::Hash; +use std::panic::catch_unwind; +use std::panic::RefUnwindSafe; + +use ads2::assert_length; +use ads2::assert_length_ne; +use ads2::assert_length_lt; +use ads2::assert_length_le; +use ads2::assert_length_gt; +use ads2::assert_length_ge; +use ads2::assert_length_unique; +use ads2::assert_length_unique_ne; +use ads2::assert_length_unique_lt; +use ads2::assert_length_unique_le; +use ads2::assert_length_unique_gt; +use ads2::assert_length_unique_ge; +use ads2::assert_contains; +use ads2::assert_not_contains; +use ads2::assert_eq_contents; +use ads2::assert_ne_contents; +use ads2::assert_subset; +use ads2::assert_not_subset; + +// ---------------------------------------------------------------- +// Fixtures +// ---------------------------------------------------------------- + +#[fixture] +fn list1() -> Vec { + return vec![1,2,4,5,13,13,13,78,78]; +} + +#[fixture] +fn list2() -> Vec { + return vec![78,13,1,4,13,78,78,5,4,2]; +} + +#[fixture] +fn list3() -> Vec { + return vec![1,2,78,78]; +} + +#[fixture] +fn list4() -> Vec { + return vec![1,2,78,78,100,45]; +} + +// ---------------------------------------------------------------- +// Test length +// ---------------------------------------------------------------- + +#[rstest] +#[case(list1(),9)] +#[case(list2(),10)] +#[case(list3(),4)] +#[case(list4(),6)] +fn test_rules_length(#[case] list: Vec, #[case] n: usize) + where T: RefUnwindSafe +{ + assert!(catch_unwind(|| { + assert_length!(list, n); + }).is_ok()); + assert!(catch_unwind(|| { + assert_length_ne!(list, n, "Length should not equal n"); + }).is_err()); +} + +#[rstest] +#[case(list1(),6)] +#[case(list2(),6)] +#[case(list3(),3)] +#[case(list4(),5)] +fn test_rules_length_ne(#[case] list: Vec, #[case] n: usize) + where T: RefUnwindSafe +{ + assert!(catch_unwind(|| { + assert_length!(list, n, "Length should be n!"); + }).is_err()); + assert!(catch_unwind(|| { + assert_length_ne!(list, n); + }).is_ok()); +} + +#[rstest] +#[case(0)] +#[case(1)] +#[case(2)] +#[case(3)] +#[case(4)] +fn test_rules_length_ge(list3: Vec, #[case] n: usize) + where T: RefUnwindSafe +{ + assert!(catch_unwind(|| { + assert_length_ge!(list3, n); + }).is_ok()); +} + +#[rstest] +#[case(5)] +#[case(100)] +fn test_rules_length_ge_error(list3: Vec, #[case] n: usize) + where T: RefUnwindSafe +{ + assert!(catch_unwind(|| { + assert_length_ge!(list3, n, "Length should be >= n!"); + }).is_err()); +} + +#[rstest] +#[case(0)] +#[case(1)] +#[case(2)] +#[case(3)] +fn test_rules_length_gt(list3: Vec, #[case] n: usize) + where T: RefUnwindSafe +{ + assert!(catch_unwind(|| { + assert_length_gt!(list3, n); + }).is_ok()); +} + +#[rstest] +#[case(4)] +#[case(5)] +#[case(100)] +fn test_rules_length_gt_error(list3: Vec, #[case] n: usize) + where T: RefUnwindSafe +{ + assert!(catch_unwind(|| { + assert_length_gt!(list3, n, "Length should be > n!"); + }).is_err()); +} + +#[rstest] +#[case(100)] +#[case(5)] +#[case(4)] +fn test_rules_length_le(list3: Vec, #[case] n: usize) + where T: RefUnwindSafe +{ + assert!(catch_unwind(|| { + assert_length_le!(list3, n); + }).is_ok()); +} + +#[rstest] +#[case(3)] +#[case(2)] +#[case(1)] +#[case(0)] +fn test_rules_length_le_error(list3: Vec, #[case] n: usize) + where T: RefUnwindSafe +{ + assert!(catch_unwind(|| { + assert_length_le!(list3, n, "Length should be <= n!"); + }).is_err()); +} + +#[rstest] +#[case(100)] +#[case(5)] +fn test_rules_length_lt(list3: Vec, #[case] n: usize) + where T: RefUnwindSafe +{ + assert!(catch_unwind(|| { + assert_length_lt!(list3, n); + }).is_ok()); +} + +#[rstest] +#[case(4)] +#[case(3)] +#[case(2)] +#[case(1)] +#[case(0)] +fn test_rules_length_lt_error(list3: Vec, #[case] n: usize) + where T: RefUnwindSafe +{ + assert!(catch_unwind(|| { + assert_length_lt!(list3, n, "Length should be < n!"); + }).is_err()); +} + +// ---------------------------------------------------------------- +// Test length unique +// ---------------------------------------------------------------- + +#[rstest] +#[case(list1(),6)] +#[case(list2(),6)] +#[case(list3(),3)] +#[case(list4(),5)] +fn test_rules_length_unique(#[case] list: Vec, #[case] n: usize) + where T: Eq + Hash + Clone + RefUnwindSafe +{ + assert!(catch_unwind(|| { + assert_length_unique!(list, n); + }).is_ok()); + assert!(catch_unwind(|| { + assert_length_unique_ne!(list, n, "Should not have n unique elements!"); + }).is_err()); +} + +#[rstest] +#[case(list1(),9)] +#[case(list2(),10)] +#[case(list3(),4)] +#[case(list4(),6)] +fn test_rules_length_unique_ne(#[case] list: Vec, #[case] n: usize) + where T: Eq + Hash + Clone + RefUnwindSafe +{ + assert!(catch_unwind(|| { + assert_length_unique!(list, n, "Should have n unique elements!"); + }).is_err()); + assert!(catch_unwind(|| { + assert_length_unique_ne!(list, n); + }).is_ok()); +} + +#[rstest] +#[case(0)] +#[case(1)] +#[case(2)] +#[case(5)] +#[case(6)] +fn test_rules_length_unique_ge(list1: Vec, #[case] n: usize) + where T: Eq + Hash + Clone + RefUnwindSafe +{ + assert!(catch_unwind(|| { + assert_length_unique_ge!(list1, n); + }).is_ok()); +} + +#[rstest] +#[case(7)] +#[case(100)] +fn test_rules_length_unique_ge_error(list1: Vec, #[case] n: usize) + where T: Eq + Hash + Clone + RefUnwindSafe +{ + assert!(catch_unwind(|| { + assert_length_unique_ge!(list1, n, "Should have >= n unique elements!"); + }).is_err()); +} + +#[rstest] +#[case(0)] +#[case(1)] +#[case(2)] +#[case(5)] +fn test_rules_length_unique_gt(list1: Vec, #[case] n: usize) + where T: Eq + Hash + Clone + RefUnwindSafe +{ + assert!(catch_unwind(|| { + assert_length_unique_gt!(list1, n); + }).is_ok()); +} + +#[rstest] +#[case(6)] +#[case(7)] +#[case(100)] +fn test_rules_length_unique_gt_error(list1: Vec, #[case] n: usize) + where T: Eq + Hash + Clone + RefUnwindSafe +{ + assert!(catch_unwind(|| { + assert_length_unique_gt!(list1, n, "Should have > n unique elements!"); + }).is_err()); +} + +#[rstest] +#[case(100)] +#[case(7)] +#[case(6)] +fn test_rules_length_unique_le(list1: Vec, #[case] n: usize) + where T: Eq + Hash + Clone + RefUnwindSafe +{ + assert!(catch_unwind(|| { + assert_length_unique_le!(list1, n); + }).is_ok()); +} + +#[rstest] +#[case(5)] +#[case(2)] +#[case(1)] +#[case(0)] +fn test_rules_length_unique_le_error(list1: Vec, #[case] n: usize) + where T: Eq + Hash + Clone + RefUnwindSafe +{ + assert!(catch_unwind(|| { + assert_length_unique_le!(list1, n, "Should have <= n unique elements!"); + }).is_err()); +} + +#[rstest] +#[case(100)] +#[case(7)] +fn test_rules_length_unique_lt(list1: Vec, #[case] n: usize) + where T: Eq + Hash + Clone + RefUnwindSafe +{ + assert!(catch_unwind(|| { + assert_length_unique_lt!(list1, n); + }).is_ok()); +} + +#[rstest] +#[case(6)] +#[case(5)] +#[case(2)] +#[case(1)] +#[case(0)] +fn test_rules_length_unique_lt_error(list1: Vec, #[case] n: usize) + where T: Eq + Hash + Clone + RefUnwindSafe +{ + assert!(catch_unwind(|| { + assert_length_unique_lt!(list1, n, "Should have < n unique elements!"); + }).is_err()); +} + +// ---------------------------------------------------------------- +// Test contains +// ---------------------------------------------------------------- + +#[rstest] +#[case(5)] +#[case(13)] +#[case(78)] +fn test_rules_contains(list1: Vec, #[case] element: T) + where T: Eq + RefUnwindSafe +{ + assert!(catch_unwind(|| { + assert_contains!(list1, element); + }).is_ok()); + assert!(catch_unwind(|| { + assert_not_contains!(list1, element, "Should not contain element!"); + }).is_err()); +} + +#[rstest] +#[case(100)] +#[case(32)] +fn test_rules_not_contains(list1: Vec, #[case] element: T) + where T: Eq + RefUnwindSafe +{ + assert!(catch_unwind(|| { + assert_contains!(list1, element, "Should contain element!"); + }).is_err()); + assert!(catch_unwind(|| { + assert_not_contains!(list1, element); + }).is_ok()); +} + +// ---------------------------------------------------------------- +// Test comparison of lists by contents +// ---------------------------------------------------------------- + +#[rstest] +fn test_rules_eq_contents( + list1: Vec, + list2: Vec, + list3: Vec, + list4: Vec, +) + where T: Eq + Clone + Hash + Debug + RefUnwindSafe +{ + assert!(catch_unwind(|| { + assert_eq_contents!(list1, list1); + assert_eq_contents!(list1, list2); + }).is_ok()); + + assert!(catch_unwind(|| { assert_eq_contents!(list1, list3, "Should be equal as sets!"); }).is_err()); + assert!(catch_unwind(|| { assert_eq_contents!(list1, list4, "Should be equal as sets!"); }).is_err()); + assert!(catch_unwind(|| { assert_eq_contents!(list2, list3, "Should be equal as sets!"); }).is_err()); + assert!(catch_unwind(|| { assert_eq_contents!(list2, list4, "Should be equal as sets!"); }).is_err()); + assert!(catch_unwind(|| { assert_eq_contents!(list3, list4, "Should be equal as sets!"); }).is_err()); + + assert!(catch_unwind(|| { assert_ne_contents!(list1, list1, "Should be unequal as sets!"); }).is_err()); + assert!(catch_unwind(|| {assert_ne_contents!(list1, list2, "Should be unequal as sets!"); }).is_err()); + + assert!(catch_unwind(|| { + assert_ne_contents!(list1, list3); + assert_ne_contents!(list1, list4); + assert_ne_contents!(list2, list3); + assert_ne_contents!(list2, list4); + assert_ne_contents!(list3, list4); + }).is_ok()); +} + +#[rstest] +fn test_rules_subset_contents( + list1: Vec, + list2: Vec, + list3: Vec, + list4: Vec, +) + where T: Eq + Clone + Hash + Debug + RefUnwindSafe +{ + assert!(catch_unwind(|| { + assert_subset!(list1, list1); + assert_subset!(list1, list2); + assert_subset!(list3, list1); + assert_subset!(list3, list2); + assert_subset!(list3, list4); + }).is_ok()); + + assert!(catch_unwind(|| { assert_subset!(list1, list3, "Should be a subset!"); }).is_err()); + assert!(catch_unwind(|| { assert_subset!(list2, list3, "Should be a subset!"); }).is_err()); + assert!(catch_unwind(|| { assert_subset!(list4, list3, "Should be a subset!"); }).is_err()); + assert!(catch_unwind(|| { assert_subset!(list4, list1, "Should be a subset!"); }).is_err()); + assert!(catch_unwind(|| { assert_subset!(list4, list2, "Should be a subset!"); }).is_err()); + + assert!(catch_unwind(|| { assert_not_subset!(list1, list1, "Should not be a subset!"); }).is_err()); + assert!(catch_unwind(|| { assert_not_subset!(list1, list2, "Should not be a subset!"); }).is_err()); + assert!(catch_unwind(|| { assert_not_subset!(list3, list1, "Should not be a subset!"); }).is_err()); + assert!(catch_unwind(|| { assert_not_subset!(list3, list2, "Should not be a subset!"); }).is_err()); + assert!(catch_unwind(|| { assert_not_subset!(list3, list4, "Should not be a subset!"); }).is_err()); + + assert!(catch_unwind(|| { + assert_not_subset!(list1, list3); + assert_not_subset!(list2, list3); + assert_not_subset!(list4, list3); + assert_not_subset!(list4, list1); + assert_not_subset!(list4, list2); + }).is_ok()); +}