/// Asserts that both collections contain exactly the same elements found in the same order.
///
/// # Usage
/// ```
/// # #[macro_use] extern crate assertx;
/// # fn main() {
/// #   let actual = vec!["a", "b", "c"];
/// #   let expected = vec!["a", "b", "c"];
///     assert_contains_exactly!(actual, expected);
/// # }
/// ```
///
/// # Examples
///
/// Will succeed, both collections containt the same elements
/// ```
/// # #[macro_use] extern crate assertx;
/// # fn main() {
///     assert_contains_exactly!(vec!["a", "b", "c"], vec!["a", "b", "c"]);
/// # }
/// ```
///
/// Will fail, actual collection has additional "c"
/// ```should_panic
/// # #[macro_use] extern crate assertx;
/// # fn main() {
///     assert_contains_exactly!(vec!["a", "b", "c"], vec!["a", "b"]);
/// # }
/// ```
///
/// Will fail, actual collection is in a different order
/// ```should_panic
/// # #[macro_use] extern crate assertx;
/// # fn main() {
///     assert_contains_exactly!(vec!["a", "c", "b"], vec!["a", "b", "c"]);
/// # }
/// ```
#[macro_export]
macro_rules! assert_contains_exactly {
    ($actual: expr, $expected: expr) => {
        let actual = $actual.clone().into_iter();
        let expected = $expected.clone().into_iter();

        assert_eq!(
            actual.len(),
            expected.len(),
            "Expected {:?} but got {:?}",
            expected.as_slice(),
            actual.as_slice()
        );

        for (a, b) in actual.clone().zip(expected.clone()) {
            assert_eq!(a, b, "Expected {:?} but got {:?}", expected.as_slice(), actual.as_slice());
        }
    };
}

#[cfg(test)]
mod tests {
    #[test]
    fn should_succeed_if_both_sides_empty() {
        assert_contains_exactly!(Vec::<bool>::new(), Vec::<bool>::new());
    }

    #[test]
    fn should_succeed_if_same_elements_in_same_order() {
        assert_contains_exactly!(vec![1, 2, 3], vec![1, 2, 3]);
    }

    #[test]
    #[should_panic(expected = "Expected [1, 2] but got [1, 2, 3]")]
    fn should_fail_if_different_number_of_elements() {
        assert_contains_exactly!(vec![1, 2, 3], vec![1, 2]);
    }

    #[test]
    #[should_panic(expected = "Expected [2] but got [1]")]
    fn should_fail_if_elements_are_not_the_same() {
        assert_contains_exactly!(vec![1], vec![2]);
    }

    #[test]
    #[should_panic(expected = "Expected [2, 1] but got [1, 2]")]
    fn should_fail_if_same_elements_but_different_order() {
        assert_contains_exactly!(vec![1, 2], &mut vec![2, 1]);
    }
}
