use core::array::{FixedSizeArray, IntoIter}; use core::convert::TryFrom; #[test] fn fixed_size_array() { let mut array = [0; 64]; let mut zero_sized = [(); 64]; let mut empty_array = [0; 0]; let mut empty_zero_sized = [(); 0]; assert_eq!(FixedSizeArray::as_slice(&array).len(), 64); assert_eq!(FixedSizeArray::as_slice(&zero_sized).len(), 64); assert_eq!(FixedSizeArray::as_slice(&empty_array).len(), 0); assert_eq!(FixedSizeArray::as_slice(&empty_zero_sized).len(), 0); assert_eq!(FixedSizeArray::as_mut_slice(&mut array).len(), 64); assert_eq!(FixedSizeArray::as_mut_slice(&mut zero_sized).len(), 64); assert_eq!(FixedSizeArray::as_mut_slice(&mut empty_array).len(), 0); assert_eq!(FixedSizeArray::as_mut_slice(&mut empty_zero_sized).len(), 0); } #[test] fn array_try_from() { macro_rules! test { ($($N:expr)+) => { $({ type Array = [u8; $N]; let array: Array = [0; $N]; let slice: &[u8] = &array[..]; let result = <&Array>::try_from(slice); assert_eq!(&array, result.unwrap()); })+ } } test! { 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 } } #[test] fn iterator_collect() { let arr = [0, 1, 2, 5, 9]; let v: Vec<_> = IntoIter::new(arr.clone()).collect(); assert_eq!(&arr[..], &v[..]); } #[test] fn iterator_rev_collect() { let arr = [0, 1, 2, 5, 9]; let v: Vec<_> = IntoIter::new(arr.clone()).rev().collect(); assert_eq!(&v[..], &[9, 5, 2, 1, 0]); } #[test] fn iterator_nth() { let v = [0, 1, 2, 3, 4]; for i in 0..v.len() { assert_eq!(IntoIter::new(v.clone()).nth(i).unwrap(), v[i]); } assert_eq!(IntoIter::new(v.clone()).nth(v.len()), None); let mut iter = IntoIter::new(v); assert_eq!(iter.nth(2).unwrap(), v[2]); assert_eq!(iter.nth(1).unwrap(), v[4]); } #[test] fn iterator_last() { let v = [0, 1, 2, 3, 4]; assert_eq!(IntoIter::new(v).last().unwrap(), 4); assert_eq!(IntoIter::new([0]).last().unwrap(), 0); let mut it = IntoIter::new([0, 9, 2, 4]); assert_eq!(it.next_back(), Some(4)); assert_eq!(it.last(), Some(2)); } #[test] fn iterator_clone() { let mut it = IntoIter::new([0, 2, 4, 6, 8]); assert_eq!(it.next(), Some(0)); assert_eq!(it.next_back(), Some(8)); let mut clone = it.clone(); assert_eq!(it.next_back(), Some(6)); assert_eq!(clone.next_back(), Some(6)); assert_eq!(it.next_back(), Some(4)); assert_eq!(clone.next_back(), Some(4)); assert_eq!(it.next(), Some(2)); assert_eq!(clone.next(), Some(2)); } #[test] fn iterator_fused() { let mut it = IntoIter::new([0, 9, 2]); assert_eq!(it.next(), Some(0)); assert_eq!(it.next(), Some(9)); assert_eq!(it.next(), Some(2)); assert_eq!(it.next(), None); assert_eq!(it.next(), None); assert_eq!(it.next(), None); assert_eq!(it.next(), None); assert_eq!(it.next(), None); } #[test] fn iterator_len() { let mut it = IntoIter::new([0, 1, 2, 5, 9]); assert_eq!(it.size_hint(), (5, Some(5))); assert_eq!(it.len(), 5); assert_eq!(it.is_empty(), false); assert_eq!(it.next(), Some(0)); assert_eq!(it.size_hint(), (4, Some(4))); assert_eq!(it.len(), 4); assert_eq!(it.is_empty(), false); assert_eq!(it.next_back(), Some(9)); assert_eq!(it.size_hint(), (3, Some(3))); assert_eq!(it.len(), 3); assert_eq!(it.is_empty(), false); // Empty let it = IntoIter::new([] as [String; 0]); assert_eq!(it.size_hint(), (0, Some(0))); assert_eq!(it.len(), 0); assert_eq!(it.is_empty(), true); } #[test] fn iterator_count() { let v = [0, 1, 2, 3, 4]; assert_eq!(IntoIter::new(v.clone()).count(), 5); let mut iter2 = IntoIter::new(v); iter2.next(); iter2.next(); assert_eq!(iter2.count(), 3); } #[test] fn iterator_flat_map() { assert!((0..5).flat_map(|i| IntoIter::new([2 * i, 2 * i + 1])).eq(0..10)); } #[test] fn iterator_debug() { let arr = [0, 1, 2, 5, 9]; assert_eq!(format!("{:?}", IntoIter::new(arr)), "IntoIter([0, 1, 2, 5, 9])",); } #[test] fn iterator_drops() { use core::cell::Cell; // This test makes sure the correct number of elements are dropped. The `R` // type is just a reference to a `Cell` that is incremented when an `R` is // dropped. #[derive(Clone)] struct Foo<'a>(&'a Cell); impl Drop for Foo<'_> { fn drop(&mut self) { self.0.set(self.0.get() + 1); } } fn five(i: &Cell) -> [Foo<'_>; 5] { // This is somewhat verbose because `Foo` does not implement `Copy` // since it implements `Drop`. Consequently, we cannot write // `[Foo(i); 5]`. [Foo(i), Foo(i), Foo(i), Foo(i), Foo(i)] } // Simple: drop new iterator. let i = Cell::new(0); { IntoIter::new(five(&i)); } assert_eq!(i.get(), 5); // Call `next()` once. let i = Cell::new(0); { let mut iter = IntoIter::new(five(&i)); let _x = iter.next(); assert_eq!(i.get(), 0); assert_eq!(iter.count(), 4); assert_eq!(i.get(), 4); } assert_eq!(i.get(), 5); // Check `clone` and calling `next`/`next_back`. let i = Cell::new(0); { let mut iter = IntoIter::new(five(&i)); iter.next(); assert_eq!(i.get(), 1); iter.next_back(); assert_eq!(i.get(), 2); let mut clone = iter.clone(); assert_eq!(i.get(), 2); iter.next(); assert_eq!(i.get(), 3); clone.next(); assert_eq!(i.get(), 4); assert_eq!(clone.count(), 2); assert_eq!(i.get(), 6); } assert_eq!(i.get(), 8); // Check via `nth`. let i = Cell::new(0); { let mut iter = IntoIter::new(five(&i)); let _x = iter.nth(2); assert_eq!(i.get(), 2); let _y = iter.last(); assert_eq!(i.get(), 3); } assert_eq!(i.get(), 5); // Check every element. let i = Cell::new(0); for (index, _x) in IntoIter::new(five(&i)).enumerate() { assert_eq!(i.get(), index); } assert_eq!(i.get(), 5); let i = Cell::new(0); for (index, _x) in IntoIter::new(five(&i)).rev().enumerate() { assert_eq!(i.get(), index); } assert_eq!(i.get(), 5); } // This test does not work on targets without panic=unwind support. // To work around this problem, test is marked is should_panic, so it will // be automagically skipped on unsuitable targets, such as // wasm32-unknown-unkown. // // It means that we use panic for indicating success. #[test] #[should_panic(expected = "test succeeded")] fn array_default_impl_avoids_leaks_on_panic() { use core::sync::atomic::{AtomicUsize, Ordering::Relaxed}; static COUNTER: AtomicUsize = AtomicUsize::new(0); #[derive(Debug)] struct Bomb(usize); impl Default for Bomb { fn default() -> Bomb { if COUNTER.load(Relaxed) == 3 { panic!("bomb limit exceeded"); } COUNTER.fetch_add(1, Relaxed); Bomb(COUNTER.load(Relaxed)) } } impl Drop for Bomb { fn drop(&mut self) { COUNTER.fetch_sub(1, Relaxed); } } let res = std::panic::catch_unwind(|| <[Bomb; 5]>::default()); let panic_msg = match res { Ok(_) => unreachable!(), Err(p) => p.downcast::<&'static str>().unwrap(), }; assert_eq!(*panic_msg, "bomb limit exceeded"); // check that all bombs are successfully dropped assert_eq!(COUNTER.load(Relaxed), 0); panic!("test succeeded") } #[test] fn empty_array_is_always_default() { struct DoesNotImplDefault; let _arr = <[DoesNotImplDefault; 0]>::default(); }