// No need to annotate this with #[cfg(test)] as the 'tests' dir is special for rustc // // All the examples have been tested with MIRI with cargo +nightly miri test --all-features // No leaks or UB have been detected so far. Great! mod tests { use astack::*; #[test] fn unsafe_stack() { unsafe { let mut stack = Stack::::new(); stack.push_unchecked("String".into()); stack.push_unchecked("Another one!".into()); assert_eq!(stack.tos_unchecked(), "Another one!"); assert_eq!(stack.len(), 2); stack.pop_unchecked(); stack.pop_unchecked(); assert_eq!(stack.tos(), None); assert!(stack.is_empty()); } } #[test] fn modify_popped() { let mut stack = Stack::::new(); stack.push("Test!".into()).unwrap(); let mut string = stack.pop().unwrap(); string.push_str("Test again!"); assert_eq!(string, "Test!Test again!"); } #[test] fn test_stack_macro() { let _empty = stack![&str; 10]; let _another_one = stack! { [usize; 10] = [1, 2, 3] }; println!("{:#?}", _empty); println!("{:#?}", _another_one); } #[test] fn test_drop() { #[derive(Debug)] struct Droppable; impl Drop for Droppable { fn drop(&mut self) { println!("Dropped!"); } } let mut stack = stack![Droppable; 10]; stack.push(Droppable).unwrap(); stack.push(Droppable).unwrap(); stack.pop(); stack.pop(); assert!(stack.pop().is_none()); println!("Here"); println!("{:#?}", stack); } #[test] fn const_assert_test() { stack! { [i32; 3] = [1] }; stack! { [i32; 3] = [1, 2] }; stack! { [i32; 3] = [1, 2, 4] }; // stack! { [i32; 3] = [1, 2, 4, 8] }; println!("{:#?}", stack! { [i32; 3] = [1, 2, 4] }); } #[test] fn test_eq() { let stack1 = stack! { [String; 10] = ["a".into()] }; let stack2 = stack! { [String; 10] = ["a".into()] }; assert_eq!(stack1, stack2); let stack_ne = stack! { [String; 10] = ["a".into(), "b".into()] }; assert_ne!(stack1, stack_ne); assert_ne!(stack2, stack_ne); let stack3 = stack! { [char; 10] = ['z', 'y', 'z'] }; let stack4 = stack! { [char; 10] = ['z', 'y', 'x'] }; assert_ne!(stack3, stack4); } #[test] fn struct_test() { use std::{cell::RefCell, rc::Rc}; #[derive(PartialEq, Debug)] struct Yo(Rc>); impl Yo { fn new(x: T) -> Self { Self(Rc::new(RefCell::new(x))) } } let stack = stack! { [Yo; 4] = [Yo::new(0)] }; let tos = unsafe { stack.tos_unchecked() }; *RefCell::<_>::borrow_mut(&tos.0) = 10; assert_eq!(stack.tos(), Some(&Yo::new(10))); let stack = stack! { [Yo; 4] = [Yo::new("Hello!".into())] }; let tos = unsafe { stack.tos_unchecked() }; *RefCell::<_>::borrow_mut(&tos.0) = "World!".into(); assert_eq!(stack.tos(), Some(&Yo::new("World!".into()))); } #[test] fn full_stack() { let mut stack = Stack::::fill_with_fn(|i| i.to_string()); assert!(stack.push(Default::default()).is_err()); stack.clear(); assert!(stack.pop().is_none()); } #[test] fn swap_tos_test() { let mut stack = Stack::::fill_with_fn(|i| i.to_string()); stack.swap_tos("new_tos".into()).unwrap(); stack.clear(); assert!(stack.swap_tos("item".into()).is_err()); } #[test] fn test_extend_array() { let x: [String; 0] = []; assert_eq!(stack![String; 0], x); let mut stack = stack![String; 10]; stack .extend_array(["Test1".to_string(), "Test2".to_string()]) .unwrap(); assert_eq!(stack, ["Test1", "Test2"]); stack .extend_array(["Test3".to_string(), "Test4".to_string()]) .unwrap(); assert_eq!(stack, ["Test1", "Test2", "Test3", "Test4"]); stack.clear(); stack.extend_array(["Final Test!".to_string()]).unwrap(); assert_eq!(stack.tos(), Some(&String::from("Final Test!"))); } #[test] fn truncate_items() { let mut stack = Stack::::fill_with_default(); assert_eq!(stack.truncate(15), Err(StackError::Underflow)); stack.truncate(0).unwrap(); assert!(stack.is_empty()); stack .extend_array([ "Test1".into(), "Test2".into(), "Test3".into(), "Test4".into(), ]) .unwrap(); assert_eq!(stack.len(), 4); } #[test] fn cut_items() { let mut stack = Stack::::fill_with_default(); let top_three = stack.cut::<3>(); assert_eq!(top_three, Ok(<[String; 3]>::default())); assert_eq!(stack, <[String; 7]>::default()); assert_eq!(stack.cut::<8>(), Err(StackError::Underflow)); let _others = stack.cut::<7>(); assert!(stack.is_empty()); } #[test] fn extend_items() { let mut stack = stack![String; 10]; let it = (0..10).map(|n| (n * n).to_string()); assert_eq!(stack.extend(it), Ok(())); assert!(stack.is_full()); let it = (0..10).map(|n| (n * n).to_string()); assert_eq!(stack.extend(it), Err(StackError::Overflow)); } #[test] fn test_clone() { let stack = stack! { [String; 5] = ["Test1".to_string(), "Test2".to_string()] }; let clone = stack.clone(); assert_eq!(clone, stack); } #[cfg(feature = "std")] #[test] fn std_test() { fn accepts_error(_err: &dyn std::error::Error) {} accepts_error(&StackError::Overflow); } #[cfg(feature = "std")] #[test] fn vec_into_stack() { let vec = std::vec![1, 2, 3, 4, 5, 6]; let stack = Stack::::try_from(vec); assert!(stack.is_ok()); let bigger_vec = std::vec![6, 7, 8, 9, 0, 1, 2, 3]; let smaller_stack = Stack::::try_from(bigger_vec); assert!(smaller_stack.is_err()); } #[cfg(feature = "std")] #[test] fn stack_into_vec() { let stack = stack! { [String; 4] = ["Hello".to_string(), "world".to_string()] }; assert_eq!(stack.tos(), Some(&String::from("world"))); let v = Vec::from(stack.clone()); dbg!(&v); dbg!(&stack); // dbg!(stack.tos()); // dbg!(v.last()); // let test = ["world".to_string(), "Hello".to_string()]; // dbg!(&test[0]); assert_eq!(v, ["Hello".to_string(), "world".to_string()]); assert_eq!(stack.tos(), v.last()); } #[cfg(feature = "std")] #[test] fn stack_into_iter_leak() { let stack = stack! { [String; 10] = ["1".into(), "3".into(), "5".into()] }; let _it = stack.into_iter(); } #[cfg(feature = "std")] #[test] fn stack_into_iter() { let stack = stack! { [String; 10] = ["1".into(), "3".into(), "5".into()] }; assert_eq!(stack.tos(), Some(&String::from("5"))); let mut it = stack.into_iter(); assert_eq!(it.next(), Some(String::from("5"))); assert_eq!(it.next_back(), Some(String::from("1"))); assert_eq!(it.next_back(), Some(String::from("3"))); assert_eq!(it.next(), None); assert_eq!(it.next_back(), None); let another_one = Stack::::try_from(vec![ "1".to_string(), "2".to_string(), "3".to_string(), "4".to_string(), "5".to_string(), "6".to_string(), "7".to_string(), "8".to_string(), "9".to_string(), "10".to_string(), ]) .unwrap(); assert_eq!(another_one.tos(), Some(&String::from("10"))); let mut it = another_one.into_iter(); assert_eq!(it.next(), Some(String::from("10"))); assert_eq!(it.next_back(), Some(String::from("1"))); assert_eq!(it.next(), Some(String::from("9"))); assert_eq!(it.next_back(), Some(String::from("2"))); dbg!(&it); assert_eq!( it.rev().collect::>(), vec![ "3".to_string(), "4".to_string(), "5".to_string(), "6".to_string(), "7".to_string(), "8".to_string(), ] ); } #[cfg(feature = "std")] #[test] fn stack_iter_clone() { let stack = stack! { [String; 4] = [ "1".to_string(), "2".to_string(), "3".to_string(), "4".to_string(), ] }; let it = stack.into_iter(); let cloned = it.clone(); assert_eq!(it, cloned); for (item1, item2) in it.zip(cloned) { assert_eq!(item1, item2); } let mut it = stack![String; 0].into_iter(); assert_eq!(it.next(), None); assert_eq!(it.next_back(), None); assert_eq!(it.next(), None); assert_eq!(it.next_back(), None); } }