diff options
| author | bors <bors@rust-lang.org> | 2020-07-27 17:39:01 +0000 |
|---|---|---|
| committer | bors <bors@rust-lang.org> | 2020-07-27 17:39:01 +0000 |
| commit | 54e000891ffccd4cbfb92146b92736c83085df63 (patch) | |
| tree | 1200bb13eb9ae22def4c43bc657bc56da8faedc6 /src/liballoc/tests | |
| parent | 4a90e36c85336d1d4b209556c1a9733210bbff19 (diff) | |
| parent | 6d9705220fec4553d693a7c19d99496e14c89edf (diff) | |
| download | rust-tmp-nightly.tar.gz | |
Auto merge of #73265 - mark-i-m:mv-std, r=<try>tmp-nightly
mv std libs to library/
This is the first step in refactoring the directory layout of this repository, with further followup steps planned (but not done yet).
Background: currently, all crates are under src/, without nested src directories and with the unconventional `lib*` prefixes (e.g., `src/libcore/lib.rs`). This directory structures is not idiomatic and makes the `src/` directory rather overwhelming. To improve contributor experience and make things a bit more approachable, we are reorganizing the repo a bit.
In this PR, we move the standard libs (basically anything that is "runtime", as opposed to part of the compiler, build system, or one of the tools, etc). The new layout moves these libraries to a new `library/` directory in the root of the repo. Additionally, we remove the `lib*` prefixes and add nested `src/` directories. The other crates/tools in this repo are not touched. So in summary:
```
library/<crate>/src/*.rs
src/<all the rest> // unchanged
```
where `<crate>` is:
- core
- alloc
- std
- test
- proc_macro
- panic_abort
- panic_unwind
- profiler_builtins
- term
- unwind
- rtstartup
- backtrace
- rustc-std-workspace-*
There was a lot of discussion about this and a few rounds of compiler team approvals, FCPs, MCPs, and nominations. The original MCP is https://github.com/rust-lang/compiler-team/issues/298. The final approval of the compiler team was given here: https://github.com/rust-lang/rust/pull/73265#issuecomment-659498446.
The name `library` was chosen to complement a later move of the compiler crates to a `compiler/` directory. There was a lot of discussion around adding the nested `src/` directories. Note that this does increase the nesting depth (plausibly important for manual traversal of the tree, e.g., through GitHub's UI or `cd`), but this is deemed to be better as it fits the standard layout of Rust crates throughout most of the ecosystem, though there is some debate about how much this should apply to multi-crate projects. Overall, there seem to be more people in favor of nested `src/` than against.
After this PR, there are no dependencies out of the `library/` directory except on the `build_helper` (or crates.io crates).
Diffstat (limited to 'src/liballoc/tests')
| -rw-r--r-- | src/liballoc/tests/arc.rs | 197 | ||||
| -rw-r--r-- | src/liballoc/tests/binary_heap.rs | 464 | ||||
| -rw-r--r-- | src/liballoc/tests/borrow.rs | 47 | ||||
| -rw-r--r-- | src/liballoc/tests/boxed.rs | 51 | ||||
| -rw-r--r-- | src/liballoc/tests/btree/map.rs | 1463 | ||||
| -rw-r--r-- | src/liballoc/tests/btree/mod.rs | 27 | ||||
| -rw-r--r-- | src/liballoc/tests/btree/set.rs | 666 | ||||
| -rw-r--r-- | src/liballoc/tests/cow_str.rs | 144 | ||||
| -rw-r--r-- | src/liballoc/tests/fmt.rs | 7 | ||||
| -rw-r--r-- | src/liballoc/tests/heap.rs | 47 | ||||
| -rw-r--r-- | src/liballoc/tests/lib.rs | 57 | ||||
| -rw-r--r-- | src/liballoc/tests/linked_list.rs | 705 | ||||
| -rw-r--r-- | src/liballoc/tests/rc.rs | 193 | ||||
| -rw-r--r-- | src/liballoc/tests/slice.rs | 1771 | ||||
| -rw-r--r-- | src/liballoc/tests/str.rs | 1899 | ||||
| -rw-r--r-- | src/liballoc/tests/string.rs | 723 | ||||
| -rw-r--r-- | src/liballoc/tests/vec.rs | 1629 | ||||
| -rw-r--r-- | src/liballoc/tests/vec_deque.rs | 1646 |
18 files changed, 0 insertions, 11736 deletions
diff --git a/src/liballoc/tests/arc.rs b/src/liballoc/tests/arc.rs deleted file mode 100644 index c02ba267056..00000000000 --- a/src/liballoc/tests/arc.rs +++ /dev/null @@ -1,197 +0,0 @@ -use std::any::Any; -use std::cell::RefCell; -use std::cmp::PartialEq; -use std::iter::TrustedLen; -use std::mem; -use std::sync::{Arc, Weak}; - -#[test] -fn uninhabited() { - enum Void {} - let mut a = Weak::<Void>::new(); - a = a.clone(); - assert!(a.upgrade().is_none()); - - let mut a: Weak<dyn Any> = a; // Unsizing - a = a.clone(); - assert!(a.upgrade().is_none()); -} - -#[test] -fn slice() { - let a: Arc<[u32; 3]> = Arc::new([3, 2, 1]); - let a: Arc<[u32]> = a; // Unsizing - let b: Arc<[u32]> = Arc::from(&[3, 2, 1][..]); // Conversion - assert_eq!(a, b); - - // Exercise is_dangling() with a DST - let mut a = Arc::downgrade(&a); - a = a.clone(); - assert!(a.upgrade().is_some()); -} - -#[test] -fn trait_object() { - let a: Arc<u32> = Arc::new(4); - let a: Arc<dyn Any> = a; // Unsizing - - // Exercise is_dangling() with a DST - let mut a = Arc::downgrade(&a); - a = a.clone(); - assert!(a.upgrade().is_some()); - - let mut b = Weak::<u32>::new(); - b = b.clone(); - assert!(b.upgrade().is_none()); - let mut b: Weak<dyn Any> = b; // Unsizing - b = b.clone(); - assert!(b.upgrade().is_none()); -} - -#[test] -fn float_nan_ne() { - let x = Arc::new(f32::NAN); - assert!(x != x); - assert!(!(x == x)); -} - -#[test] -fn partial_eq() { - struct TestPEq(RefCell<usize>); - impl PartialEq for TestPEq { - fn eq(&self, other: &TestPEq) -> bool { - *self.0.borrow_mut() += 1; - *other.0.borrow_mut() += 1; - true - } - } - let x = Arc::new(TestPEq(RefCell::new(0))); - assert!(x == x); - assert!(!(x != x)); - assert_eq!(*x.0.borrow(), 4); -} - -#[test] -fn eq() { - #[derive(Eq)] - struct TestEq(RefCell<usize>); - impl PartialEq for TestEq { - fn eq(&self, other: &TestEq) -> bool { - *self.0.borrow_mut() += 1; - *other.0.borrow_mut() += 1; - true - } - } - let x = Arc::new(TestEq(RefCell::new(0))); - assert!(x == x); - assert!(!(x != x)); - assert_eq!(*x.0.borrow(), 0); -} - -// The test code below is identical to that in `rc.rs`. -// For better maintainability we therefore define this type alias. -type Rc<T> = Arc<T>; - -const SHARED_ITER_MAX: u16 = 100; - -fn assert_trusted_len<I: TrustedLen>(_: &I) {} - -#[test] -fn shared_from_iter_normal() { - // Exercise the base implementation for non-`TrustedLen` iterators. - { - // `Filter` is never `TrustedLen` since we don't - // know statically how many elements will be kept: - let iter = (0..SHARED_ITER_MAX).filter(|x| x % 2 == 0).map(Box::new); - - // Collecting into a `Vec<T>` or `Rc<[T]>` should make no difference: - let vec = iter.clone().collect::<Vec<_>>(); - let rc = iter.collect::<Rc<[_]>>(); - assert_eq!(&*vec, &*rc); - - // Clone a bit and let these get dropped. - { - let _rc_2 = rc.clone(); - let _rc_3 = rc.clone(); - let _rc_4 = Rc::downgrade(&_rc_3); - } - } // Drop what hasn't been here. -} - -#[test] -fn shared_from_iter_trustedlen_normal() { - // Exercise the `TrustedLen` implementation under normal circumstances - // where `size_hint()` matches `(_, Some(exact_len))`. - { - let iter = (0..SHARED_ITER_MAX).map(Box::new); - assert_trusted_len(&iter); - - // Collecting into a `Vec<T>` or `Rc<[T]>` should make no difference: - let vec = iter.clone().collect::<Vec<_>>(); - let rc = iter.collect::<Rc<[_]>>(); - assert_eq!(&*vec, &*rc); - assert_eq!(mem::size_of::<Box<u16>>() * SHARED_ITER_MAX as usize, mem::size_of_val(&*rc)); - - // Clone a bit and let these get dropped. - { - let _rc_2 = rc.clone(); - let _rc_3 = rc.clone(); - let _rc_4 = Rc::downgrade(&_rc_3); - } - } // Drop what hasn't been here. - - // Try a ZST to make sure it is handled well. - { - let iter = (0..SHARED_ITER_MAX).map(drop); - let vec = iter.clone().collect::<Vec<_>>(); - let rc = iter.collect::<Rc<[_]>>(); - assert_eq!(&*vec, &*rc); - assert_eq!(0, mem::size_of_val(&*rc)); - { - let _rc_2 = rc.clone(); - let _rc_3 = rc.clone(); - let _rc_4 = Rc::downgrade(&_rc_3); - } - } -} - -#[test] -#[should_panic = "I've almost got 99 problems."] -fn shared_from_iter_trustedlen_panic() { - // Exercise the `TrustedLen` implementation when `size_hint()` matches - // `(_, Some(exact_len))` but where `.next()` drops before the last iteration. - let iter = (0..SHARED_ITER_MAX).map(|val| match val { - 98 => panic!("I've almost got 99 problems."), - _ => Box::new(val), - }); - assert_trusted_len(&iter); - let _ = iter.collect::<Rc<[_]>>(); - - panic!("I am unreachable."); -} - -#[test] -fn shared_from_iter_trustedlen_no_fuse() { - // Exercise the `TrustedLen` implementation when `size_hint()` matches - // `(_, Some(exact_len))` but where the iterator does not behave in a fused manner. - struct Iter(std::vec::IntoIter<Option<Box<u8>>>); - - unsafe impl TrustedLen for Iter {} - - impl Iterator for Iter { - fn size_hint(&self) -> (usize, Option<usize>) { - (2, Some(2)) - } - - type Item = Box<u8>; - - fn next(&mut self) -> Option<Self::Item> { - self.0.next().flatten() - } - } - - let vec = vec![Some(Box::new(42)), Some(Box::new(24)), None, Some(Box::new(12))]; - let iter = Iter(vec.into_iter()); - assert_trusted_len(&iter); - assert_eq!(&[Box::new(42), Box::new(24)], &*iter.collect::<Rc<[_]>>()); -} diff --git a/src/liballoc/tests/binary_heap.rs b/src/liballoc/tests/binary_heap.rs deleted file mode 100644 index 62084ccf53c..00000000000 --- a/src/liballoc/tests/binary_heap.rs +++ /dev/null @@ -1,464 +0,0 @@ -use std::collections::binary_heap::{Drain, PeekMut}; -use std::collections::BinaryHeap; -use std::iter::TrustedLen; -use std::panic::{catch_unwind, AssertUnwindSafe}; -use std::sync::atomic::{AtomicU32, Ordering}; - -#[test] -fn test_iterator() { - let data = vec![5, 9, 3]; - let iterout = [9, 5, 3]; - let heap = BinaryHeap::from(data); - let mut i = 0; - for el in &heap { - assert_eq!(*el, iterout[i]); - i += 1; - } -} - -#[test] -fn test_iter_rev_cloned_collect() { - let data = vec![5, 9, 3]; - let iterout = vec![3, 5, 9]; - let pq = BinaryHeap::from(data); - - let v: Vec<_> = pq.iter().rev().cloned().collect(); - assert_eq!(v, iterout); -} - -#[test] -fn test_into_iter_collect() { - let data = vec![5, 9, 3]; - let iterout = vec![9, 5, 3]; - let pq = BinaryHeap::from(data); - - let v: Vec<_> = pq.into_iter().collect(); - assert_eq!(v, iterout); -} - -#[test] -fn test_into_iter_size_hint() { - let data = vec![5, 9]; - let pq = BinaryHeap::from(data); - - let mut it = pq.into_iter(); - - assert_eq!(it.size_hint(), (2, Some(2))); - assert_eq!(it.next(), Some(9)); - - assert_eq!(it.size_hint(), (1, Some(1))); - assert_eq!(it.next(), Some(5)); - - assert_eq!(it.size_hint(), (0, Some(0))); - assert_eq!(it.next(), None); -} - -#[test] -fn test_into_iter_rev_collect() { - let data = vec![5, 9, 3]; - let iterout = vec![3, 5, 9]; - let pq = BinaryHeap::from(data); - - let v: Vec<_> = pq.into_iter().rev().collect(); - assert_eq!(v, iterout); -} - -#[test] -fn test_into_iter_sorted_collect() { - let heap = BinaryHeap::from(vec![2, 4, 6, 2, 1, 8, 10, 3, 5, 7, 0, 9, 1]); - let it = heap.into_iter_sorted(); - let sorted = it.collect::<Vec<_>>(); - assert_eq!(sorted, vec![10, 9, 8, 7, 6, 5, 4, 3, 2, 2, 1, 1, 0]); -} - -#[test] -fn test_drain_sorted_collect() { - let mut heap = BinaryHeap::from(vec![2, 4, 6, 2, 1, 8, 10, 3, 5, 7, 0, 9, 1]); - let it = heap.drain_sorted(); - let sorted = it.collect::<Vec<_>>(); - assert_eq!(sorted, vec![10, 9, 8, 7, 6, 5, 4, 3, 2, 2, 1, 1, 0]); -} - -fn check_exact_size_iterator<I: ExactSizeIterator>(len: usize, it: I) { - let mut it = it; - - for i in 0..it.len() { - let (lower, upper) = it.size_hint(); - assert_eq!(Some(lower), upper); - assert_eq!(lower, len - i); - assert_eq!(it.len(), len - i); - it.next(); - } - assert_eq!(it.len(), 0); - assert!(it.is_empty()); -} - -#[test] -fn test_exact_size_iterator() { - let heap = BinaryHeap::from(vec![2, 4, 6, 2, 1, 8, 10, 3, 5, 7, 0, 9, 1]); - check_exact_size_iterator(heap.len(), heap.iter()); - check_exact_size_iterator(heap.len(), heap.clone().into_iter()); - check_exact_size_iterator(heap.len(), heap.clone().into_iter_sorted()); - check_exact_size_iterator(heap.len(), heap.clone().drain()); - check_exact_size_iterator(heap.len(), heap.clone().drain_sorted()); -} - -fn check_trusted_len<I: TrustedLen>(len: usize, it: I) { - let mut it = it; - for i in 0..len { - let (lower, upper) = it.size_hint(); - if upper.is_some() { - assert_eq!(Some(lower), upper); - assert_eq!(lower, len - i); - } - it.next(); - } -} - -#[test] -fn test_trusted_len() { - let heap = BinaryHeap::from(vec![2, 4, 6, 2, 1, 8, 10, 3, 5, 7, 0, 9, 1]); - check_trusted_len(heap.len(), heap.clone().into_iter_sorted()); - check_trusted_len(heap.len(), heap.clone().drain_sorted()); -} - -#[test] -fn test_peek_and_pop() { - let data = vec![2, 4, 6, 2, 1, 8, 10, 3, 5, 7, 0, 9, 1]; - let mut sorted = data.clone(); - sorted.sort(); - let mut heap = BinaryHeap::from(data); - while !heap.is_empty() { - assert_eq!(heap.peek().unwrap(), sorted.last().unwrap()); - assert_eq!(heap.pop().unwrap(), sorted.pop().unwrap()); - } -} - -#[test] -fn test_peek_mut() { - let data = vec![2, 4, 6, 2, 1, 8, 10, 3, 5, 7, 0, 9, 1]; - let mut heap = BinaryHeap::from(data); - assert_eq!(heap.peek(), Some(&10)); - { - let mut top = heap.peek_mut().unwrap(); - *top -= 2; - } - assert_eq!(heap.peek(), Some(&9)); -} - -#[test] -fn test_peek_mut_pop() { - let data = vec![2, 4, 6, 2, 1, 8, 10, 3, 5, 7, 0, 9, 1]; - let mut heap = BinaryHeap::from(data); - assert_eq!(heap.peek(), Some(&10)); - { - let mut top = heap.peek_mut().unwrap(); - *top -= 2; - assert_eq!(PeekMut::pop(top), 8); - } - assert_eq!(heap.peek(), Some(&9)); -} - -#[test] -fn test_push() { - let mut heap = BinaryHeap::from(vec![2, 4, 9]); - assert_eq!(heap.len(), 3); - assert!(*heap.peek().unwrap() == 9); - heap.push(11); - assert_eq!(heap.len(), 4); - assert!(*heap.peek().unwrap() == 11); - heap.push(5); - assert_eq!(heap.len(), 5); - assert!(*heap.peek().unwrap() == 11); - heap.push(27); - assert_eq!(heap.len(), 6); - assert!(*heap.peek().unwrap() == 27); - heap.push(3); - assert_eq!(heap.len(), 7); - assert!(*heap.peek().unwrap() == 27); - heap.push(103); - assert_eq!(heap.len(), 8); - assert!(*heap.peek().unwrap() == 103); -} - -#[test] -fn test_push_unique() { - let mut heap = BinaryHeap::<Box<_>>::from(vec![box 2, box 4, box 9]); - assert_eq!(heap.len(), 3); - assert!(**heap.peek().unwrap() == 9); - heap.push(box 11); - assert_eq!(heap.len(), 4); - assert!(**heap.peek().unwrap() == 11); - heap.push(box 5); - assert_eq!(heap.len(), 5); - assert!(**heap.peek().unwrap() == 11); - heap.push(box 27); - assert_eq!(heap.len(), 6); - assert!(**heap.peek().unwrap() == 27); - heap.push(box 3); - assert_eq!(heap.len(), 7); - assert!(**heap.peek().unwrap() == 27); - heap.push(box 103); - assert_eq!(heap.len(), 8); - assert!(**heap.peek().unwrap() == 103); -} - -fn check_to_vec(mut data: Vec<i32>) { - let heap = BinaryHeap::from(data.clone()); - let mut v = heap.clone().into_vec(); - v.sort(); - data.sort(); - - assert_eq!(v, data); - assert_eq!(heap.into_sorted_vec(), data); -} - -#[test] -fn test_to_vec() { - check_to_vec(vec![]); - check_to_vec(vec![5]); - check_to_vec(vec![3, 2]); - check_to_vec(vec![2, 3]); - check_to_vec(vec![5, 1, 2]); - check_to_vec(vec![1, 100, 2, 3]); - check_to_vec(vec![1, 3, 5, 7, 9, 2, 4, 6, 8, 0]); - check_to_vec(vec![2, 4, 6, 2, 1, 8, 10, 3, 5, 7, 0, 9, 1]); - check_to_vec(vec![9, 11, 9, 9, 9, 9, 11, 2, 3, 4, 11, 9, 0, 0, 0, 0]); - check_to_vec(vec![0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10]); - check_to_vec(vec![10, 9, 8, 7, 6, 5, 4, 3, 2, 1, 0]); - check_to_vec(vec![0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0, 0, 0, 1, 2]); - check_to_vec(vec![5, 4, 3, 2, 1, 5, 4, 3, 2, 1, 5, 4, 3, 2, 1]); -} - -#[test] -fn test_empty_pop() { - let mut heap = BinaryHeap::<i32>::new(); - assert!(heap.pop().is_none()); -} - -#[test] -fn test_empty_peek() { - let empty = BinaryHeap::<i32>::new(); - assert!(empty.peek().is_none()); -} - -#[test] -fn test_empty_peek_mut() { - let mut empty = BinaryHeap::<i32>::new(); - assert!(empty.peek_mut().is_none()); -} - -#[test] -fn test_from_iter() { - let xs = vec![9, 8, 7, 6, 5, 4, 3, 2, 1]; - - let mut q: BinaryHeap<_> = xs.iter().rev().cloned().collect(); - - for &x in &xs { - assert_eq!(q.pop().unwrap(), x); - } -} - -#[test] -fn test_drain() { - let mut q: BinaryHeap<_> = [9, 8, 7, 6, 5, 4, 3, 2, 1].iter().cloned().collect(); - - assert_eq!(q.drain().take(5).count(), 5); - - assert!(q.is_empty()); -} - -#[test] -fn test_drain_sorted() { - let mut q: BinaryHeap<_> = [9, 8, 7, 6, 5, 4, 3, 2, 1].iter().cloned().collect(); - - assert_eq!(q.drain_sorted().take(5).collect::<Vec<_>>(), vec![9, 8, 7, 6, 5]); - - assert!(q.is_empty()); -} - -#[test] -fn test_drain_sorted_leak() { - static DROPS: AtomicU32 = AtomicU32::new(0); - - #[derive(Clone, PartialEq, Eq, PartialOrd, Ord)] - struct D(u32, bool); - - impl Drop for D { - fn drop(&mut self) { - DROPS.fetch_add(1, Ordering::SeqCst); - - if self.1 { - panic!("panic in `drop`"); - } - } - } - - let mut q = BinaryHeap::from(vec![ - D(0, false), - D(1, false), - D(2, false), - D(3, true), - D(4, false), - D(5, false), - ]); - - catch_unwind(AssertUnwindSafe(|| drop(q.drain_sorted()))).ok(); - - assert_eq!(DROPS.load(Ordering::SeqCst), 6); -} - -#[test] -fn test_extend_ref() { - let mut a = BinaryHeap::new(); - a.push(1); - a.push(2); - - a.extend(&[3, 4, 5]); - - assert_eq!(a.len(), 5); - assert_eq!(a.into_sorted_vec(), [1, 2, 3, 4, 5]); - - let mut a = BinaryHeap::new(); - a.push(1); - a.push(2); - let mut b = BinaryHeap::new(); - b.push(3); - b.push(4); - b.push(5); - - a.extend(&b); - - assert_eq!(a.len(), 5); - assert_eq!(a.into_sorted_vec(), [1, 2, 3, 4, 5]); -} - -#[test] -fn test_append() { - let mut a = BinaryHeap::from(vec![-10, 1, 2, 3, 3]); - let mut b = BinaryHeap::from(vec![-20, 5, 43]); - - a.append(&mut b); - - assert_eq!(a.into_sorted_vec(), [-20, -10, 1, 2, 3, 3, 5, 43]); - assert!(b.is_empty()); -} - -#[test] -fn test_append_to_empty() { - let mut a = BinaryHeap::new(); - let mut b = BinaryHeap::from(vec![-20, 5, 43]); - - a.append(&mut b); - - assert_eq!(a.into_sorted_vec(), [-20, 5, 43]); - assert!(b.is_empty()); -} - -#[test] -fn test_extend_specialization() { - let mut a = BinaryHeap::from(vec![-10, 1, 2, 3, 3]); - let b = BinaryHeap::from(vec![-20, 5, 43]); - - a.extend(b); - - assert_eq!(a.into_sorted_vec(), [-20, -10, 1, 2, 3, 3, 5, 43]); -} - -#[allow(dead_code)] -fn assert_covariance() { - fn drain<'new>(d: Drain<'static, &'static str>) -> Drain<'new, &'new str> { - d - } -} - -#[test] -fn test_retain() { - let mut a = BinaryHeap::from(vec![-10, -5, 1, 2, 4, 13]); - a.retain(|x| x % 2 == 0); - - assert_eq!(a.into_sorted_vec(), [-10, 2, 4]) -} - -// old binaryheap failed this test -// -// Integrity means that all elements are present after a comparison panics, -// even if the order may not be correct. -// -// Destructors must be called exactly once per element. -// FIXME: re-enable emscripten once it can unwind again -#[test] -#[cfg(not(target_os = "emscripten"))] -fn panic_safe() { - use rand::{seq::SliceRandom, thread_rng}; - use std::cmp; - use std::panic::{self, AssertUnwindSafe}; - use std::sync::atomic::{AtomicUsize, Ordering}; - - static DROP_COUNTER: AtomicUsize = AtomicUsize::new(0); - - #[derive(Eq, PartialEq, Ord, Clone, Debug)] - struct PanicOrd<T>(T, bool); - - impl<T> Drop for PanicOrd<T> { - fn drop(&mut self) { - // update global drop count - DROP_COUNTER.fetch_add(1, Ordering::SeqCst); - } - } - - impl<T: PartialOrd> PartialOrd for PanicOrd<T> { - fn partial_cmp(&self, other: &Self) -> Option<cmp::Ordering> { - if self.1 || other.1 { - panic!("Panicking comparison"); - } - self.0.partial_cmp(&other.0) - } - } - let mut rng = thread_rng(); - const DATASZ: usize = 32; - // Miri is too slow - let ntest = if cfg!(miri) { 1 } else { 10 }; - - // don't use 0 in the data -- we want to catch the zeroed-out case. - let data = (1..=DATASZ).collect::<Vec<_>>(); - - // since it's a fuzzy test, run several tries. - for _ in 0..ntest { - for i in 1..=DATASZ { - DROP_COUNTER.store(0, Ordering::SeqCst); - - let mut panic_ords: Vec<_> = - data.iter().filter(|&&x| x != i).map(|&x| PanicOrd(x, false)).collect(); - let panic_item = PanicOrd(i, true); - - // heapify the sane items - panic_ords.shuffle(&mut rng); - let mut heap = BinaryHeap::from(panic_ords); - let inner_data; - - { - // push the panicking item to the heap and catch the panic - let thread_result = { - let mut heap_ref = AssertUnwindSafe(&mut heap); - panic::catch_unwind(move || { - heap_ref.push(panic_item); - }) - }; - assert!(thread_result.is_err()); - - // Assert no elements were dropped - let drops = DROP_COUNTER.load(Ordering::SeqCst); - assert!(drops == 0, "Must not drop items. drops={}", drops); - inner_data = heap.clone().into_vec(); - drop(heap); - } - let drops = DROP_COUNTER.load(Ordering::SeqCst); - assert_eq!(drops, DATASZ); - - let mut data_sorted = inner_data.into_iter().map(|p| p.0).collect::<Vec<_>>(); - data_sorted.sort(); - assert_eq!(data_sorted, data); - } - } -} diff --git a/src/liballoc/tests/borrow.rs b/src/liballoc/tests/borrow.rs deleted file mode 100644 index 8bfcf323f67..00000000000 --- a/src/liballoc/tests/borrow.rs +++ /dev/null @@ -1,47 +0,0 @@ -use std::borrow::{Cow, ToOwned}; -use std::ffi::{CStr, OsStr}; -use std::path::Path; -use std::rc::Rc; -use std::sync::Arc; - -macro_rules! test_from_cow { - ($value:ident => $($ty:ty),+) => {$( - let borrowed = <$ty>::from(Cow::Borrowed($value)); - let owned = <$ty>::from(Cow::Owned($value.to_owned())); - assert_eq!($value, &*borrowed); - assert_eq!($value, &*owned); - )+}; - ($value:ident : & $ty:ty) => { - test_from_cow!($value => Box<$ty>, Rc<$ty>, Arc<$ty>); - } -} - -#[test] -fn test_from_cow_slice() { - let slice: &[i32] = &[1, 2, 3]; - test_from_cow!(slice: &[i32]); -} - -#[test] -fn test_from_cow_str() { - let string = "hello"; - test_from_cow!(string: &str); -} - -#[test] -fn test_from_cow_c_str() { - let string = CStr::from_bytes_with_nul(b"hello\0").unwrap(); - test_from_cow!(string: &CStr); -} - -#[test] -fn test_from_cow_os_str() { - let string = OsStr::new("hello"); - test_from_cow!(string: &OsStr); -} - -#[test] -fn test_from_cow_path() { - let path = Path::new("hello"); - test_from_cow!(path: &Path); -} diff --git a/src/liballoc/tests/boxed.rs b/src/liballoc/tests/boxed.rs deleted file mode 100644 index 5377485da8f..00000000000 --- a/src/liballoc/tests/boxed.rs +++ /dev/null @@ -1,51 +0,0 @@ -use std::mem::MaybeUninit; -use std::ptr::NonNull; - -#[test] -fn unitialized_zero_size_box() { - assert_eq!( - &*Box::<()>::new_uninit() as *const _, - NonNull::<MaybeUninit<()>>::dangling().as_ptr(), - ); - assert_eq!( - Box::<[()]>::new_uninit_slice(4).as_ptr(), - NonNull::<MaybeUninit<()>>::dangling().as_ptr(), - ); - assert_eq!( - Box::<[String]>::new_uninit_slice(0).as_ptr(), - NonNull::<MaybeUninit<String>>::dangling().as_ptr(), - ); -} - -#[derive(Clone, PartialEq, Eq, Debug)] -struct Dummy { - _data: u8, -} - -#[test] -fn box_clone_and_clone_from_equivalence() { - for size in (0..8).map(|i| 2usize.pow(i)) { - let control = vec![Dummy { _data: 42 }; size].into_boxed_slice(); - let clone = control.clone(); - let mut copy = vec![Dummy { _data: 84 }; size].into_boxed_slice(); - copy.clone_from(&control); - assert_eq!(control, clone); - assert_eq!(control, copy); - } -} - -/// This test might give a false positive in case the box realocates, but the alocator keeps the -/// original pointer. -/// -/// On the other hand it won't give a false negative, if it fails than the memory was definitly not -/// reused -#[test] -fn box_clone_from_ptr_stability() { - for size in (0..8).map(|i| 2usize.pow(i)) { - let control = vec![Dummy { _data: 42 }; size].into_boxed_slice(); - let mut copy = vec![Dummy { _data: 84 }; size].into_boxed_slice(); - let copy_raw = copy.as_ptr() as usize; - copy.clone_from(&control); - assert_eq!(copy.as_ptr() as usize, copy_raw); - } -} diff --git a/src/liballoc/tests/btree/map.rs b/src/liballoc/tests/btree/map.rs deleted file mode 100644 index f9f81716e35..00000000000 --- a/src/liballoc/tests/btree/map.rs +++ /dev/null @@ -1,1463 +0,0 @@ -use std::collections::btree_map::Entry::{Occupied, Vacant}; -use std::collections::BTreeMap; -use std::convert::TryFrom; -use std::fmt::Debug; -use std::iter::FromIterator; -use std::mem; -use std::ops::Bound::{self, Excluded, Included, Unbounded}; -use std::ops::RangeBounds; -use std::panic::{catch_unwind, AssertUnwindSafe}; -use std::rc::Rc; -use std::sync::atomic::{AtomicUsize, Ordering}; - -use super::DeterministicRng; - -// Value of node::CAPACITY, thus capacity of a tree with a single level, -// i.e. a tree who's root is a leaf node at height 0. -const NODE_CAPACITY: usize = 11; - -// Minimum number of elements to insert in order to guarantee a tree with 2 levels, -// i.e. a tree who's root is an internal node at height 1, with edges to leaf nodes. -// It's not the minimum size: removing an element from such a tree does not always reduce height. -const MIN_INSERTS_HEIGHT_1: usize = NODE_CAPACITY + 1; - -// Minimum number of elements to insert in order to guarantee a tree with 3 levels, -// i.e. a tree who's root is an internal node at height 2, with edges to more internal nodes. -// It's not the minimum size: removing an element from such a tree does not always reduce height. -const MIN_INSERTS_HEIGHT_2: usize = NODE_CAPACITY + (NODE_CAPACITY + 1) * NODE_CAPACITY + 1; - -// Gather all references from a mutable iterator and make sure Miri notices if -// using them is dangerous. -fn test_all_refs<'a, T: 'a>(dummy: &mut T, iter: impl Iterator<Item = &'a mut T>) { - // Gather all those references. - let mut refs: Vec<&mut T> = iter.collect(); - // Use them all. Twice, to be sure we got all interleavings. - for r in refs.iter_mut() { - mem::swap(dummy, r); - } - for r in refs { - mem::swap(dummy, r); - } -} - -#[test] -fn test_basic_large() { - let mut map = BTreeMap::new(); - // Miri is too slow - let size = if cfg!(miri) { MIN_INSERTS_HEIGHT_2 } else { 10000 }; - assert_eq!(map.len(), 0); - - for i in 0..size { - assert_eq!(map.insert(i, 10 * i), None); - assert_eq!(map.len(), i + 1); - } - - assert_eq!(map.first_key_value(), Some((&0, &0))); - assert_eq!(map.last_key_value(), Some((&(size - 1), &(10 * (size - 1))))); - assert_eq!(map.first_entry().unwrap().key(), &0); - assert_eq!(map.last_entry().unwrap().key(), &(size - 1)); - - for i in 0..size { - assert_eq!(map.get(&i).unwrap(), &(i * 10)); - } - - for i in size..size * 2 { - assert_eq!(map.get(&i), None); - } - - for i in 0..size { - assert_eq!(map.insert(i, 100 * i), Some(10 * i)); - assert_eq!(map.len(), size); - } - - for i in 0..size { - assert_eq!(map.get(&i).unwrap(), &(i * 100)); - } - - for i in 0..size / 2 { - assert_eq!(map.remove(&(i * 2)), Some(i * 200)); - assert_eq!(map.len(), size - i - 1); - } - - for i in 0..size / 2 { - assert_eq!(map.get(&(2 * i)), None); - assert_eq!(map.get(&(2 * i + 1)).unwrap(), &(i * 200 + 100)); - } - - for i in 0..size / 2 { - assert_eq!(map.remove(&(2 * i)), None); - assert_eq!(map.remove(&(2 * i + 1)), Some(i * 200 + 100)); - assert_eq!(map.len(), size / 2 - i - 1); - } -} - -#[test] -fn test_basic_small() { - let mut map = BTreeMap::new(); - // Empty, root is absent (None): - assert_eq!(map.remove(&1), None); - assert_eq!(map.len(), 0); - assert_eq!(map.get(&1), None); - assert_eq!(map.get_mut(&1), None); - assert_eq!(map.first_key_value(), None); - assert_eq!(map.last_key_value(), None); - assert_eq!(map.keys().count(), 0); - assert_eq!(map.values().count(), 0); - assert_eq!(map.range(..).next(), None); - assert_eq!(map.range(..1).next(), None); - assert_eq!(map.range(1..).next(), None); - assert_eq!(map.range(1..=1).next(), None); - assert_eq!(map.range(1..2).next(), None); - assert_eq!(map.insert(1, 1), None); - - // 1 key-value pair: - assert_eq!(map.len(), 1); - assert_eq!(map.get(&1), Some(&1)); - assert_eq!(map.get_mut(&1), Some(&mut 1)); - assert_eq!(map.first_key_value(), Some((&1, &1))); - assert_eq!(map.last_key_value(), Some((&1, &1))); - assert_eq!(map.keys().collect::<Vec<_>>(), vec![&1]); - assert_eq!(map.values().collect::<Vec<_>>(), vec![&1]); - assert_eq!(map.insert(1, 2), Some(1)); - assert_eq!(map.len(), 1); - assert_eq!(map.get(&1), Some(&2)); - assert_eq!(map.get_mut(&1), Some(&mut 2)); - assert_eq!(map.first_key_value(), Some((&1, &2))); - assert_eq!(map.last_key_value(), Some((&1, &2))); - assert_eq!(map.keys().collect::<Vec<_>>(), vec![&1]); - assert_eq!(map.values().collect::<Vec<_>>(), vec![&2]); - assert_eq!(map.insert(2, 4), None); - - // 2 key-value pairs: - assert_eq!(map.len(), 2); - assert_eq!(map.get(&2), Some(&4)); - assert_eq!(map.get_mut(&2), Some(&mut 4)); - assert_eq!(map.first_key_value(), Some((&1, &2))); - assert_eq!(map.last_key_value(), Some((&2, &4))); - assert_eq!(map.keys().collect::<Vec<_>>(), vec![&1, &2]); - assert_eq!(map.values().collect::<Vec<_>>(), vec![&2, &4]); - assert_eq!(map.remove(&1), Some(2)); - - // 1 key-value pair: - assert_eq!(map.len(), 1); - assert_eq!(map.get(&1), None); - assert_eq!(map.get_mut(&1), None); - assert_eq!(map.get(&2), Some(&4)); - assert_eq!(map.get_mut(&2), Some(&mut 4)); - assert_eq!(map.first_key_value(), Some((&2, &4))); - assert_eq!(map.last_key_value(), Some((&2, &4))); - assert_eq!(map.keys().collect::<Vec<_>>(), vec![&2]); - assert_eq!(map.values().collect::<Vec<_>>(), vec![&4]); - assert_eq!(map.remove(&2), Some(4)); - - // Empty but root is owned (Some(...)): - assert_eq!(map.len(), 0); - assert_eq!(map.get(&1), None); - assert_eq!(map.get_mut(&1), None); - assert_eq!(map.first_key_value(), None); - assert_eq!(map.last_key_value(), None); - assert_eq!(map.keys().count(), 0); - assert_eq!(map.values().count(), 0); - assert_eq!(map.range(..).next(), None); - assert_eq!(map.range(..1).next(), None); - assert_eq!(map.range(1..).next(), None); - assert_eq!(map.range(1..=1).next(), None); - assert_eq!(map.range(1..2).next(), None); - assert_eq!(map.remove(&1), None); -} - -#[test] -fn test_iter() { - // Miri is too slow - let size = if cfg!(miri) { 200 } else { 10000 }; - - let mut map: BTreeMap<_, _> = (0..size).map(|i| (i, i)).collect(); - - fn test<T>(size: usize, mut iter: T) - where - T: Iterator<Item = (usize, usize)>, - { - for i in 0..size { - assert_eq!(iter.size_hint(), (size - i, Some(size - i))); - assert_eq!(iter.next().unwrap(), (i, i)); - } - assert_eq!(iter.size_hint(), (0, Some(0))); - assert_eq!(iter.next(), None); - } - test(size, map.iter().map(|(&k, &v)| (k, v))); - test(size, map.iter_mut().map(|(&k, &mut v)| (k, v))); - test(size, map.into_iter()); -} - -#[test] -fn test_iter_rev() { - // Miri is too slow - let size = if cfg!(miri) { 200 } else { 10000 }; - - let mut map: BTreeMap<_, _> = (0..size).map(|i| (i, i)).collect(); - - fn test<T>(size: usize, mut iter: T) - where - T: Iterator<Item = (usize, usize)>, - { - for i in 0..size { - assert_eq!(iter.size_hint(), (size - i, Some(size - i))); - assert_eq!(iter.next().unwrap(), (size - i - 1, size - i - 1)); - } - assert_eq!(iter.size_hint(), (0, Some(0))); - assert_eq!(iter.next(), None); - } - test(size, map.iter().rev().map(|(&k, &v)| (k, v))); - test(size, map.iter_mut().rev().map(|(&k, &mut v)| (k, v))); - test(size, map.into_iter().rev()); -} - -/// Specifically tests iter_mut's ability to mutate the value of pairs in-line -fn do_test_iter_mut_mutation<T>(size: usize) -where - T: Copy + Debug + Ord + TryFrom<usize>, - <T as std::convert::TryFrom<usize>>::Error: std::fmt::Debug, -{ - let zero = T::try_from(0).unwrap(); - let mut map: BTreeMap<T, T> = (0..size).map(|i| (T::try_from(i).unwrap(), zero)).collect(); - - // Forward and backward iteration sees enough pairs (also tested elsewhere) - assert_eq!(map.iter_mut().count(), size); - assert_eq!(map.iter_mut().rev().count(), size); - - // Iterate forwards, trying to mutate to unique values - for (i, (k, v)) in map.iter_mut().enumerate() { - assert_eq!(*k, T::try_from(i).unwrap()); - assert_eq!(*v, zero); - *v = T::try_from(i + 1).unwrap(); - } - - // Iterate backwards, checking that mutations succeeded and trying to mutate again - for (i, (k, v)) in map.iter_mut().rev().enumerate() { - assert_eq!(*k, T::try_from(size - i - 1).unwrap()); - assert_eq!(*v, T::try_from(size - i).unwrap()); - *v = T::try_from(2 * size - i).unwrap(); - } - - // Check that backward mutations succeeded - for (i, (k, v)) in map.iter_mut().enumerate() { - assert_eq!(*k, T::try_from(i).unwrap()); - assert_eq!(*v, T::try_from(size + i + 1).unwrap()); - } -} - -#[derive(Clone, Copy, Debug, Eq, PartialEq, PartialOrd, Ord)] -#[repr(align(32))] -struct Align32(usize); - -impl TryFrom<usize> for Align32 { - type Error = (); - - fn try_from(s: usize) -> Result<Align32, ()> { - Ok(Align32(s)) - } -} - -#[test] -fn test_iter_mut_mutation() { - // Check many alignments and trees with roots at various heights. - do_test_iter_mut_mutation::<u8>(0); - do_test_iter_mut_mutation::<u8>(1); - do_test_iter_mut_mutation::<u8>(MIN_INSERTS_HEIGHT_1); - do_test_iter_mut_mutation::<u8>(127); // not enough unique values to test MIN_INSERTS_HEIGHT_2 - do_test_iter_mut_mutation::<u16>(1); - do_test_iter_mut_mutation::<u16>(MIN_INSERTS_HEIGHT_1); - do_test_iter_mut_mutation::<u16>(MIN_INSERTS_HEIGHT_2); - do_test_iter_mut_mutation::<u32>(1); - do_test_iter_mut_mutation::<u32>(MIN_INSERTS_HEIGHT_1); - do_test_iter_mut_mutation::<u32>(MIN_INSERTS_HEIGHT_2); - do_test_iter_mut_mutation::<u64>(1); - do_test_iter_mut_mutation::<u64>(MIN_INSERTS_HEIGHT_1); - do_test_iter_mut_mutation::<u64>(MIN_INSERTS_HEIGHT_2); - do_test_iter_mut_mutation::<u128>(1); - do_test_iter_mut_mutation::<u128>(MIN_INSERTS_HEIGHT_1); - do_test_iter_mut_mutation::<u128>(MIN_INSERTS_HEIGHT_2); - do_test_iter_mut_mutation::<Align32>(1); - do_test_iter_mut_mutation::<Align32>(MIN_INSERTS_HEIGHT_1); - do_test_iter_mut_mutation::<Align32>(MIN_INSERTS_HEIGHT_2); -} - -#[test] -#[cfg_attr(miri, ignore)] // FIXME: fails in Miri <https://github.com/rust-lang/rust/issues/73915> -fn test_values_mut() { - let mut a: BTreeMap<_, _> = (0..MIN_INSERTS_HEIGHT_2).map(|i| (i, i)).collect(); - test_all_refs(&mut 13, a.values_mut()); -} - -#[test] -fn test_values_mut_mutation() { - let mut a = BTreeMap::new(); - a.insert(1, String::from("hello")); - a.insert(2, String::from("goodbye")); - - for value in a.values_mut() { - value.push_str("!"); - } - - let values: Vec<String> = a.values().cloned().collect(); - assert_eq!(values, [String::from("hello!"), String::from("goodbye!")]); -} - -#[test] -#[cfg_attr(miri, ignore)] // FIXME: fails in Miri <https://github.com/rust-lang/rust/issues/73915> -fn test_iter_entering_root_twice() { - let mut map: BTreeMap<_, _> = (0..2).map(|i| (i, i)).collect(); - let mut it = map.iter_mut(); - let front = it.next().unwrap(); - let back = it.next_back().unwrap(); - assert_eq!(front, (&0, &mut 0)); - assert_eq!(back, (&1, &mut 1)); - *front.1 = 24; - *back.1 = 42; - assert_eq!(front, (&0, &mut 24)); - assert_eq!(back, (&1, &mut 42)); -} - -#[test] -#[cfg_attr(miri, ignore)] // FIXME: fails in Miri <https://github.com/rust-lang/rust/issues/73915> -fn test_iter_descending_to_same_node_twice() { - let mut map: BTreeMap<_, _> = (0..MIN_INSERTS_HEIGHT_1).map(|i| (i, i)).collect(); - let mut it = map.iter_mut(); - // Descend into first child. - let front = it.next().unwrap(); - // Descend into first child again, after running through second child. - while it.next_back().is_some() {} - // Check immutable access. - assert_eq!(front, (&0, &mut 0)); - // Perform mutable access. - *front.1 = 42; -} - -#[test] -fn test_iter_mixed() { - // Miri is too slow - let size = if cfg!(miri) { 200 } else { 10000 }; - - let mut map: BTreeMap<_, _> = (0..size).map(|i| (i, i)).collect(); - - fn test<T>(size: usize, mut iter: T) - where - T: Iterator<Item = (usize, usize)> + DoubleEndedIterator, - { - for i in 0..size / 4 { - assert_eq!(iter.size_hint(), (size - i * 2, Some(size - i * 2))); - assert_eq!(iter.next().unwrap(), (i, i)); - assert_eq!(iter.next_back().unwrap(), (size - i - 1, size - i - 1)); - } - for i in size / 4..size * 3 / 4 { - assert_eq!(iter.size_hint(), (size * 3 / 4 - i, Some(size * 3 / 4 - i))); - assert_eq!(iter.next().unwrap(), (i, i)); - } - assert_eq!(iter.size_hint(), (0, Some(0))); - assert_eq!(iter.next(), None); - } - test(size, map.iter().map(|(&k, &v)| (k, v))); - test(size, map.iter_mut().map(|(&k, &mut v)| (k, v))); - test(size, map.into_iter()); -} - -#[test] -#[cfg_attr(miri, ignore)] // FIXME: fails in Miri <https://github.com/rust-lang/rust/issues/73915> -fn test_iter_min_max() { - let mut a = BTreeMap::new(); - assert_eq!(a.iter().min(), None); - assert_eq!(a.iter().max(), None); - assert_eq!(a.iter_mut().min(), None); - assert_eq!(a.iter_mut().max(), None); - assert_eq!(a.range(..).min(), None); - assert_eq!(a.range(..).max(), None); - assert_eq!(a.range_mut(..).min(), None); - assert_eq!(a.range_mut(..).max(), None); - assert_eq!(a.keys().min(), None); - assert_eq!(a.keys().max(), None); - assert_eq!(a.values().min(), None); - assert_eq!(a.values().max(), None); - assert_eq!(a.values_mut().min(), None); - assert_eq!(a.values_mut().max(), None); - a.insert(1, 42); - a.insert(2, 24); - assert_eq!(a.iter().min(), Some((&1, &42))); - assert_eq!(a.iter().max(), Some((&2, &24))); - assert_eq!(a.iter_mut().min(), Some((&1, &mut 42))); - assert_eq!(a.iter_mut().max(), Some((&2, &mut 24))); - assert_eq!(a.range(..).min(), Some((&1, &42))); - assert_eq!(a.range(..).max(), Some((&2, &24))); - assert_eq!(a.range_mut(..).min(), Some((&1, &mut 42))); - assert_eq!(a.range_mut(..).max(), Some((&2, &mut 24))); - assert_eq!(a.keys().min(), Some(&1)); - assert_eq!(a.keys().max(), Some(&2)); - assert_eq!(a.values().min(), Some(&24)); - assert_eq!(a.values().max(), Some(&42)); - assert_eq!(a.values_mut().min(), Some(&mut 24)); - assert_eq!(a.values_mut().max(), Some(&mut 42)); -} - -fn range_keys(map: &BTreeMap<i32, i32>, range: impl RangeBounds<i32>) -> Vec<i32> { - map.range(range) - .map(|(&k, &v)| { - assert_eq!(k, v); - k - }) - .collect() -} - -#[test] -fn test_range_small() { - let size = 4; - - let map: BTreeMap<_, _> = (1..=size).map(|i| (i, i)).collect(); - let all: Vec<_> = (1..=size).collect(); - let (first, last) = (vec![all[0]], vec![all[size as usize - 1]]); - - assert_eq!(range_keys(&map, (Excluded(0), Excluded(size + 1))), all); - assert_eq!(range_keys(&map, (Excluded(0), Included(size + 1))), all); - assert_eq!(range_keys(&map, (Excluded(0), Included(size))), all); - assert_eq!(range_keys(&map, (Excluded(0), Unbounded)), all); - assert_eq!(range_keys(&map, (Included(0), Excluded(size + 1))), all); - assert_eq!(range_keys(&map, (Included(0), Included(size + 1))), all); - assert_eq!(range_keys(&map, (Included(0), Included(size))), all); - assert_eq!(range_keys(&map, (Included(0), Unbounded)), all); - assert_eq!(range_keys(&map, (Included(1), Excluded(size + 1))), all); - assert_eq!(range_keys(&map, (Included(1), Included(size + 1))), all); - assert_eq!(range_keys(&map, (Included(1), Included(size))), all); - assert_eq!(range_keys(&map, (Included(1), Unbounded)), all); - assert_eq!(range_keys(&map, (Unbounded, Excluded(size + 1))), all); - assert_eq!(range_keys(&map, (Unbounded, Included(size + 1))), all); - assert_eq!(range_keys(&map, (Unbounded, Included(size))), all); - assert_eq!(range_keys(&map, ..), all); - - assert_eq!(range_keys(&map, (Excluded(0), Excluded(1))), vec![]); - assert_eq!(range_keys(&map, (Excluded(0), Included(0))), vec![]); - assert_eq!(range_keys(&map, (Included(0), Included(0))), vec![]); - assert_eq!(range_keys(&map, (Included(0), Excluded(1))), vec![]); - assert_eq!(range_keys(&map, (Unbounded, Excluded(1))), vec![]); - assert_eq!(range_keys(&map, (Unbounded, Included(0))), vec![]); - assert_eq!(range_keys(&map, (Excluded(0), Excluded(2))), first); - assert_eq!(range_keys(&map, (Excluded(0), Included(1))), first); - assert_eq!(range_keys(&map, (Included(0), Excluded(2))), first); - assert_eq!(range_keys(&map, (Included(0), Included(1))), first); - assert_eq!(range_keys(&map, (Included(1), Excluded(2))), first); - assert_eq!(range_keys(&map, (Included(1), Included(1))), first); - assert_eq!(range_keys(&map, (Unbounded, Excluded(2))), first); - assert_eq!(range_keys(&map, (Unbounded, Included(1))), first); - assert_eq!(range_keys(&map, (Excluded(size - 1), Excluded(size + 1))), last); - assert_eq!(range_keys(&map, (Excluded(size - 1), Included(size + 1))), last); - assert_eq!(range_keys(&map, (Excluded(size - 1), Included(size))), last); - assert_eq!(range_keys(&map, (Excluded(size - 1), Unbounded)), last); - assert_eq!(range_keys(&map, (Included(size), Excluded(size + 1))), last); - assert_eq!(range_keys(&map, (Included(size), Included(size + 1))), last); - assert_eq!(range_keys(&map, (Included(size), Included(size))), last); - assert_eq!(range_keys(&map, (Included(size), Unbounded)), last); - assert_eq!(range_keys(&map, (Excluded(size), Excluded(size + 1))), vec![]); - assert_eq!(range_keys(&map, (Excluded(size), Included(size))), vec![]); - assert_eq!(range_keys(&map, (Excluded(size), Unbounded)), vec![]); - assert_eq!(range_keys(&map, (Included(size + 1), Excluded(size + 1))), vec![]); - assert_eq!(range_keys(&map, (Included(size + 1), Included(size + 1))), vec![]); - assert_eq!(range_keys(&map, (Included(size + 1), Unbounded)), vec![]); - - assert_eq!(range_keys(&map, ..3), vec![1, 2]); - assert_eq!(range_keys(&map, 3..), vec![3, 4]); - assert_eq!(range_keys(&map, 2..=3), vec![2, 3]); -} - -#[test] -fn test_range_height_1() { - // Tests tree with a root and 2 leaves. Depending on details we don't want or need - // to rely upon, the single key at the root will be 6 or 7. - - let map: BTreeMap<_, _> = (1..=MIN_INSERTS_HEIGHT_1 as i32).map(|i| (i, i)).collect(); - for &root in &[6, 7] { - assert_eq!(range_keys(&map, (Excluded(root), Excluded(root + 1))), vec![]); - assert_eq!(range_keys(&map, (Excluded(root), Included(root + 1))), vec![root + 1]); - assert_eq!(range_keys(&map, (Included(root), Excluded(root + 1))), vec![root]); - assert_eq!(range_keys(&map, (Included(root), Included(root + 1))), vec![root, root + 1]); - - assert_eq!(range_keys(&map, (Excluded(root - 1), Excluded(root))), vec![]); - assert_eq!(range_keys(&map, (Included(root - 1), Excluded(root))), vec![root - 1]); - assert_eq!(range_keys(&map, (Excluded(root - 1), Included(root))), vec![root]); - assert_eq!(range_keys(&map, (Included(root - 1), Included(root))), vec![root - 1, root]); - } -} - -#[test] -fn test_range_large() { - let size = 200; - - let map: BTreeMap<_, _> = (1..=size).map(|i| (i, i)).collect(); - let all: Vec<_> = (1..=size).collect(); - let (first, last) = (vec![all[0]], vec![all[size as usize - 1]]); - - assert_eq!(range_keys(&map, (Excluded(0), Excluded(size + 1))), all); - assert_eq!(range_keys(&map, (Excluded(0), Included(size + 1))), all); - assert_eq!(range_keys(&map, (Excluded(0), Included(size))), all); - assert_eq!(range_keys(&map, (Excluded(0), Unbounded)), all); - assert_eq!(range_keys(&map, (Included(0), Excluded(size + 1))), all); - assert_eq!(range_keys(&map, (Included(0), Included(size + 1))), all); - assert_eq!(range_keys(&map, (Included(0), Included(size))), all); - assert_eq!(range_keys(&map, (Included(0), Unbounded)), all); - assert_eq!(range_keys(&map, (Included(1), Excluded(size + 1))), all); - assert_eq!(range_keys(&map, (Included(1), Included(size + 1))), all); - assert_eq!(range_keys(&map, (Included(1), Included(size))), all); - assert_eq!(range_keys(&map, (Included(1), Unbounded)), all); - assert_eq!(range_keys(&map, (Unbounded, Excluded(size + 1))), all); - assert_eq!(range_keys(&map, (Unbounded, Included(size + 1))), all); - assert_eq!(range_keys(&map, (Unbounded, Included(size))), all); - assert_eq!(range_keys(&map, ..), all); - - assert_eq!(range_keys(&map, (Excluded(0), Excluded(1))), vec![]); - assert_eq!(range_keys(&map, (Excluded(0), Included(0))), vec![]); - assert_eq!(range_keys(&map, (Included(0), Included(0))), vec![]); - assert_eq!(range_keys(&map, (Included(0), Excluded(1))), vec![]); - assert_eq!(range_keys(&map, (Unbounded, Excluded(1))), vec![]); - assert_eq!(range_keys(&map, (Unbounded, Included(0))), vec![]); - assert_eq!(range_keys(&map, (Excluded(0), Excluded(2))), first); - assert_eq!(range_keys(&map, (Excluded(0), Included(1))), first); - assert_eq!(range_keys(&map, (Included(0), Excluded(2))), first); - assert_eq!(range_keys(&map, (Included(0), Included(1))), first); - assert_eq!(range_keys(&map, (Included(1), Excluded(2))), first); - assert_eq!(range_keys(&map, (Included(1), Included(1))), first); - assert_eq!(range_keys(&map, (Unbounded, Excluded(2))), first); - assert_eq!(range_keys(&map, (Unbounded, Included(1))), first); - assert_eq!(range_keys(&map, (Excluded(size - 1), Excluded(size + 1))), last); - assert_eq!(range_keys(&map, (Excluded(size - 1), Included(size + 1))), last); - assert_eq!(range_keys(&map, (Excluded(size - 1), Included(size))), last); - assert_eq!(range_keys(&map, (Excluded(size - 1), Unbounded)), last); - assert_eq!(range_keys(&map, (Included(size), Excluded(size + 1))), last); - assert_eq!(range_keys(&map, (Included(size), Included(size + 1))), last); - assert_eq!(range_keys(&map, (Included(size), Included(size))), last); - assert_eq!(range_keys(&map, (Included(size), Unbounded)), last); - assert_eq!(range_keys(&map, (Excluded(size), Excluded(size + 1))), vec![]); - assert_eq!(range_keys(&map, (Excluded(size), Included(size))), vec![]); - assert_eq!(range_keys(&map, (Excluded(size), Unbounded)), vec![]); - assert_eq!(range_keys(&map, (Included(size + 1), Excluded(size + 1))), vec![]); - assert_eq!(range_keys(&map, (Included(size + 1), Included(size + 1))), vec![]); - assert_eq!(range_keys(&map, (Included(size + 1), Unbounded)), vec![]); - - fn check<'a, L, R>(lhs: L, rhs: R) - where - L: IntoIterator<Item = (&'a i32, &'a i32)>, - R: IntoIterator<Item = (&'a i32, &'a i32)>, - { - let lhs: Vec<_> = lhs.into_iter().collect(); - let rhs: Vec<_> = rhs.into_iter().collect(); - assert_eq!(lhs, rhs); - } - - check(map.range(..=100), map.range(..101)); - check(map.range(5..=8), vec![(&5, &5), (&6, &6), (&7, &7), (&8, &8)]); - check(map.range(-1..=2), vec![(&1, &1), (&2, &2)]); -} - -#[test] -fn test_range_inclusive_max_value() { - let max = usize::MAX; - let map: BTreeMap<_, _> = vec![(max, 0)].into_iter().collect(); - - assert_eq!(map.range(max..=max).collect::<Vec<_>>(), &[(&max, &0)]); -} - -#[test] -fn test_range_equal_empty_cases() { - let map: BTreeMap<_, _> = (0..5).map(|i| (i, i)).collect(); - assert_eq!(map.range((Included(2), Excluded(2))).next(), None); - assert_eq!(map.range((Excluded(2), Included(2))).next(), None); -} - -#[test] -#[should_panic] -fn test_range_equal_excluded() { - let map: BTreeMap<_, _> = (0..5).map(|i| (i, i)).collect(); - map.range((Excluded(2), Excluded(2))); -} - -#[test] -#[should_panic] -fn test_range_backwards_1() { - let map: BTreeMap<_, _> = (0..5).map(|i| (i, i)).collect(); - map.range((Included(3), Included(2))); -} - -#[test] -#[should_panic] -fn test_range_backwards_2() { - let map: BTreeMap<_, _> = (0..5).map(|i| (i, i)).collect(); - map.range((Included(3), Excluded(2))); -} - -#[test] -#[should_panic] -fn test_range_backwards_3() { - let map: BTreeMap<_, _> = (0..5).map(|i| (i, i)).collect(); - map.range((Excluded(3), Included(2))); -} - -#[test] -#[should_panic] -fn test_range_backwards_4() { - let map: BTreeMap<_, _> = (0..5).map(|i| (i, i)).collect(); - map.range((Excluded(3), Excluded(2))); -} - -#[test] -fn test_range_1000() { - // Miri is too slow - let size = if cfg!(miri) { MIN_INSERTS_HEIGHT_2 as u32 } else { 1000 }; - let map: BTreeMap<_, _> = (0..size).map(|i| (i, i)).collect(); - - fn test(map: &BTreeMap<u32, u32>, size: u32, min: Bound<&u32>, max: Bound<&u32>) { - let mut kvs = map.range((min, max)).map(|(&k, &v)| (k, v)); - let mut pairs = (0..size).map(|i| (i, i)); - - for (kv, pair) in kvs.by_ref().zip(pairs.by_ref()) { - assert_eq!(kv, pair); - } - assert_eq!(kvs.next(), None); - assert_eq!(pairs.next(), None); - } - test(&map, size, Included(&0), Excluded(&size)); - test(&map, size, Unbounded, Excluded(&size)); - test(&map, size, Included(&0), Included(&(size - 1))); - test(&map, size, Unbounded, Included(&(size - 1))); - test(&map, size, Included(&0), Unbounded); - test(&map, size, Unbounded, Unbounded); -} - -#[test] -fn test_range_borrowed_key() { - let mut map = BTreeMap::new(); - map.insert("aardvark".to_string(), 1); - map.insert("baboon".to_string(), 2); - map.insert("coyote".to_string(), 3); - map.insert("dingo".to_string(), 4); - // NOTE: would like to use simply "b".."d" here... - let mut iter = map.range::<str, _>((Included("b"), Excluded("d"))); - assert_eq!(iter.next(), Some((&"baboon".to_string(), &2))); - assert_eq!(iter.next(), Some((&"coyote".to_string(), &3))); - assert_eq!(iter.next(), None); -} - -#[test] -fn test_range() { - let size = 200; - // Miri is too slow - let step = if cfg!(miri) { 66 } else { 1 }; - let map: BTreeMap<_, _> = (0..size).map(|i| (i, i)).collect(); - - for i in (0..size).step_by(step) { - for j in (i..size).step_by(step) { - let mut kvs = map.range((Included(&i), Included(&j))).map(|(&k, &v)| (k, v)); - let mut pairs = (i..=j).map(|i| (i, i)); - - for (kv, pair) in kvs.by_ref().zip(pairs.by_ref()) { - assert_eq!(kv, pair); - } - assert_eq!(kvs.next(), None); - assert_eq!(pairs.next(), None); - } - } -} - -#[test] -fn test_range_mut() { - let size = 200; - // Miri is too slow - let step = if cfg!(miri) { 66 } else { 1 }; - let mut map: BTreeMap<_, _> = (0..size).map(|i| (i, i)).collect(); - - for i in (0..size).step_by(step) { - for j in (i..size).step_by(step) { - let mut kvs = map.range_mut((Included(&i), Included(&j))).map(|(&k, &mut v)| (k, v)); - let mut pairs = (i..=j).map(|i| (i, i)); - - for (kv, pair) in kvs.by_ref().zip(pairs.by_ref()) { - assert_eq!(kv, pair); - } - assert_eq!(kvs.next(), None); - assert_eq!(pairs.next(), None); - } - } -} - -mod test_drain_filter { - use super::*; - - #[test] - fn empty() { - let mut map: BTreeMap<i32, i32> = BTreeMap::new(); - map.drain_filter(|_, _| unreachable!("there's nothing to decide on")); - assert!(map.is_empty()); - } - - #[test] - fn consuming_nothing() { - let pairs = (0..3).map(|i| (i, i)); - let mut map: BTreeMap<_, _> = pairs.collect(); - assert!(map.drain_filter(|_, _| false).eq(std::iter::empty())); - } - - #[test] - fn consuming_all() { - let pairs = (0..3).map(|i| (i, i)); - let mut map: BTreeMap<_, _> = pairs.clone().collect(); - assert!(map.drain_filter(|_, _| true).eq(pairs)); - } - - #[test] - fn mutating_and_keeping() { - let pairs = (0..3).map(|i| (i, i)); - let mut map: BTreeMap<_, _> = pairs.collect(); - assert!( - map.drain_filter(|_, v| { - *v += 6; - false - }) - .eq(std::iter::empty()) - ); - assert!(map.keys().copied().eq(0..3)); - assert!(map.values().copied().eq(6..9)); - } - - #[test] - fn mutating_and_removing() { - let pairs = (0..3).map(|i| (i, i)); - let mut map: BTreeMap<_, _> = pairs.collect(); - assert!( - map.drain_filter(|_, v| { - *v += 6; - true - }) - .eq((0..3).map(|i| (i, i + 6))) - ); - assert!(map.is_empty()); - } - - #[test] - fn underfull_keeping_all() { - let pairs = (0..3).map(|i| (i, i)); - let mut map: BTreeMap<_, _> = pairs.collect(); - map.drain_filter(|_, _| false); - assert!(map.keys().copied().eq(0..3)); - } - - #[test] - fn underfull_removing_one() { - let pairs = (0..3).map(|i| (i, i)); - for doomed in 0..3 { - let mut map: BTreeMap<_, _> = pairs.clone().collect(); - map.drain_filter(|i, _| *i == doomed); - assert_eq!(map.len(), 2); - } - } - - #[test] - fn underfull_keeping_one() { - let pairs = (0..3).map(|i| (i, i)); - for sacred in 0..3 { - let mut map: BTreeMap<_, _> = pairs.clone().collect(); - map.drain_filter(|i, _| *i != sacred); - assert!(map.keys().copied().eq(sacred..=sacred)); - } - } - - #[test] - fn underfull_removing_all() { - let pairs = (0..3).map(|i| (i, i)); - let mut map: BTreeMap<_, _> = pairs.collect(); - map.drain_filter(|_, _| true); - assert!(map.is_empty()); - } - - #[test] - fn height_0_keeping_all() { - let pairs = (0..NODE_CAPACITY).map(|i| (i, i)); - let mut map: BTreeMap<_, _> = pairs.collect(); - map.drain_filter(|_, _| false); - assert!(map.keys().copied().eq(0..NODE_CAPACITY)); - } - - #[test] - fn height_0_removing_one() { - let pairs = (0..NODE_CAPACITY).map(|i| (i, i)); - for doomed in 0..NODE_CAPACITY { - let mut map: BTreeMap<_, _> = pairs.clone().collect(); - map.drain_filter(|i, _| *i == doomed); - assert_eq!(map.len(), NODE_CAPACITY - 1); - } - } - - #[test] - fn height_0_keeping_one() { - let pairs = (0..NODE_CAPACITY).map(|i| (i, i)); - for sacred in 0..NODE_CAPACITY { - let mut map: BTreeMap<_, _> = pairs.clone().collect(); - map.drain_filter(|i, _| *i != sacred); - assert!(map.keys().copied().eq(sacred..=sacred)); - } - } - - #[test] - fn height_0_removing_all() { - let pairs = (0..NODE_CAPACITY).map(|i| (i, i)); - let mut map: BTreeMap<_, _> = pairs.collect(); - map.drain_filter(|_, _| true); - assert!(map.is_empty()); - } - - #[test] - fn height_0_keeping_half() { - let mut map: BTreeMap<_, _> = (0..16).map(|i| (i, i)).collect(); - assert_eq!(map.drain_filter(|i, _| *i % 2 == 0).count(), 8); - assert_eq!(map.len(), 8); - } - - #[test] - fn height_1_removing_all() { - let pairs = (0..MIN_INSERTS_HEIGHT_1).map(|i| (i, i)); - let mut map: BTreeMap<_, _> = pairs.collect(); - map.drain_filter(|_, _| true); - assert!(map.is_empty()); - } - - #[test] - fn height_1_removing_one() { - let pairs = (0..MIN_INSERTS_HEIGHT_1).map(|i| (i, i)); - for doomed in 0..MIN_INSERTS_HEIGHT_1 { - let mut map: BTreeMap<_, _> = pairs.clone().collect(); - map.drain_filter(|i, _| *i == doomed); - assert_eq!(map.len(), MIN_INSERTS_HEIGHT_1 - 1); - } - } - - #[test] - fn height_1_keeping_one() { - let pairs = (0..MIN_INSERTS_HEIGHT_1).map(|i| (i, i)); - for sacred in 0..MIN_INSERTS_HEIGHT_1 { - let mut map: BTreeMap<_, _> = pairs.clone().collect(); - map.drain_filter(|i, _| *i != sacred); - assert!(map.keys().copied().eq(sacred..=sacred)); - } - } - - #[cfg(not(miri))] // Miri is too slow - #[test] - fn height_2_removing_one() { - let pairs = (0..MIN_INSERTS_HEIGHT_2).map(|i| (i, i)); - for doomed in (0..MIN_INSERTS_HEIGHT_2).step_by(12) { - let mut map: BTreeMap<_, _> = pairs.clone().collect(); - map.drain_filter(|i, _| *i == doomed); - assert_eq!(map.len(), MIN_INSERTS_HEIGHT_2 - 1); - } - } - - #[cfg(not(miri))] // Miri is too slow - #[test] - fn height_2_keeping_one() { - let pairs = (0..MIN_INSERTS_HEIGHT_2).map(|i| (i, i)); - for sacred in (0..MIN_INSERTS_HEIGHT_2).step_by(12) { - let mut map: BTreeMap<_, _> = pairs.clone().collect(); - map.drain_filter(|i, _| *i != sacred); - assert!(map.keys().copied().eq(sacred..=sacred)); - } - } - - #[test] - fn height_2_removing_all() { - let pairs = (0..MIN_INSERTS_HEIGHT_2).map(|i| (i, i)); - let mut map: BTreeMap<_, _> = pairs.collect(); - map.drain_filter(|_, _| true); - assert!(map.is_empty()); - } - - #[test] - fn drop_panic_leak() { - static PREDS: AtomicUsize = AtomicUsize::new(0); - static DROPS: AtomicUsize = AtomicUsize::new(0); - - struct D; - impl Drop for D { - fn drop(&mut self) { - if DROPS.fetch_add(1, Ordering::SeqCst) == 1 { - panic!("panic in `drop`"); - } - } - } - - // Keys are multiples of 4, so that each key is counted by a hexadecimal digit. - let mut map = (0..3).map(|i| (i * 4, D)).collect::<BTreeMap<_, _>>(); - - catch_unwind(move || { - drop(map.drain_filter(|i, _| { - PREDS.fetch_add(1usize << i, Ordering::SeqCst); - true - })) - }) - .unwrap_err(); - - assert_eq!(PREDS.load(Ordering::SeqCst), 0x011); - assert_eq!(DROPS.load(Ordering::SeqCst), 3); - } - - #[test] - fn pred_panic_leak() { - static PREDS: AtomicUsize = AtomicUsize::new(0); - static DROPS: AtomicUsize = AtomicUsize::new(0); - - struct D; - impl Drop for D { - fn drop(&mut self) { - DROPS.fetch_add(1, Ordering::SeqCst); - } - } - - // Keys are multiples of 4, so that each key is counted by a hexadecimal digit. - let mut map = (0..3).map(|i| (i * 4, D)).collect::<BTreeMap<_, _>>(); - - catch_unwind(AssertUnwindSafe(|| { - drop(map.drain_filter(|i, _| { - PREDS.fetch_add(1usize << i, Ordering::SeqCst); - match i { - 0 => true, - _ => panic!(), - } - })) - })) - .unwrap_err(); - - assert_eq!(PREDS.load(Ordering::SeqCst), 0x011); - assert_eq!(DROPS.load(Ordering::SeqCst), 1); - assert_eq!(map.len(), 2); - assert_eq!(map.first_entry().unwrap().key(), &4); - assert_eq!(map.last_entry().unwrap().key(), &8); - } - - // Same as above, but attempt to use the iterator again after the panic in the predicate - #[test] - fn pred_panic_reuse() { - static PREDS: AtomicUsize = AtomicUsize::new(0); - static DROPS: AtomicUsize = AtomicUsize::new(0); - - struct D; - impl Drop for D { - fn drop(&mut self) { - DROPS.fetch_add(1, Ordering::SeqCst); - } - } - - // Keys are multiples of 4, so that each key is counted by a hexadecimal digit. - let mut map = (0..3).map(|i| (i * 4, D)).collect::<BTreeMap<_, _>>(); - - { - let mut it = map.drain_filter(|i, _| { - PREDS.fetch_add(1usize << i, Ordering::SeqCst); - match i { - 0 => true, - _ => panic!(), - } - }); - catch_unwind(AssertUnwindSafe(|| while it.next().is_some() {})).unwrap_err(); - // Iterator behaviour after a panic is explicitly unspecified, - // so this is just the current implementation: - let result = catch_unwind(AssertUnwindSafe(|| it.next())); - assert!(matches!(result, Ok(None))); - } - - assert_eq!(PREDS.load(Ordering::SeqCst), 0x011); - assert_eq!(DROPS.load(Ordering::SeqCst), 1); - assert_eq!(map.len(), 2); - assert_eq!(map.first_entry().unwrap().key(), &4); - assert_eq!(map.last_entry().unwrap().key(), &8); - } -} - -#[test] -fn test_borrow() { - // make sure these compile -- using the Borrow trait - { - let mut map = BTreeMap::new(); - map.insert("0".to_string(), 1); - assert_eq!(map["0"], 1); - } - - { - let mut map = BTreeMap::new(); - map.insert(Box::new(0), 1); - assert_eq!(map[&0], 1); - } - - { - let mut map = BTreeMap::new(); - map.insert(Box::new([0, 1]) as Box<[i32]>, 1); - assert_eq!(map[&[0, 1][..]], 1); - } - - { - let mut map = BTreeMap::new(); - map.insert(Rc::new(0), 1); - assert_eq!(map[&0], 1); - } -} - -#[test] -fn test_entry() { - let xs = [(1, 10), (2, 20), (3, 30), (4, 40), (5, 50), (6, 60)]; - - let mut map: BTreeMap<_, _> = xs.iter().cloned().collect(); - - // Existing key (insert) - match map.entry(1) { - Vacant(_) => unreachable!(), - Occupied(mut view) => { - assert_eq!(view.get(), &10); - assert_eq!(view.insert(100), 10); - } - } - assert_eq!(map.get(&1).unwrap(), &100); - assert_eq!(map.len(), 6); - - // Existing key (update) - match map.entry(2) { - Vacant(_) => unreachable!(), - Occupied(mut view) => { - let v = view.get_mut(); - *v *= 10; - } - } - assert_eq!(map.get(&2).unwrap(), &200); - assert_eq!(map.len(), 6); - - // Existing key (take) - match map.entry(3) { - Vacant(_) => unreachable!(), - Occupied(view) => { - assert_eq!(view.remove(), 30); - } - } - assert_eq!(map.get(&3), None); - assert_eq!(map.len(), 5); - - // Inexistent key (insert) - match map.entry(10) { - Occupied(_) => unreachable!(), - Vacant(view) => { - assert_eq!(*view.insert(1000), 1000); - } - } - assert_eq!(map.get(&10).unwrap(), &1000); - assert_eq!(map.len(), 6); -} - -#[test] -fn test_extend_ref() { - let mut a = BTreeMap::new(); - a.insert(1, "one"); - let mut b = BTreeMap::new(); - b.insert(2, "two"); - b.insert(3, "three"); - - a.extend(&b); - - assert_eq!(a.len(), 3); - assert_eq!(a[&1], "one"); - assert_eq!(a[&2], "two"); - assert_eq!(a[&3], "three"); -} - -#[test] -fn test_zst() { - let mut m = BTreeMap::new(); - assert_eq!(m.len(), 0); - - assert_eq!(m.insert((), ()), None); - assert_eq!(m.len(), 1); - - assert_eq!(m.insert((), ()), Some(())); - assert_eq!(m.len(), 1); - assert_eq!(m.iter().count(), 1); - - m.clear(); - assert_eq!(m.len(), 0); - - for _ in 0..100 { - m.insert((), ()); - } - - assert_eq!(m.len(), 1); - assert_eq!(m.iter().count(), 1); -} - -// This test's only purpose is to ensure that zero-sized keys with nonsensical orderings -// do not cause segfaults when used with zero-sized values. All other map behavior is -// undefined. -#[test] -fn test_bad_zst() { - use std::cmp::Ordering; - - struct Bad; - - impl PartialEq for Bad { - fn eq(&self, _: &Self) -> bool { - false - } - } - - impl Eq for Bad {} - - impl PartialOrd for Bad { - fn partial_cmp(&self, _: &Self) -> Option<Ordering> { - Some(Ordering::Less) - } - } - - impl Ord for Bad { - fn cmp(&self, _: &Self) -> Ordering { - Ordering::Less - } - } - - let mut m = BTreeMap::new(); - - for _ in 0..100 { - m.insert(Bad, Bad); - } -} - -#[test] -fn test_clone() { - let mut map = BTreeMap::new(); - let size = MIN_INSERTS_HEIGHT_1; - assert_eq!(map.len(), 0); - - for i in 0..size { - assert_eq!(map.insert(i, 10 * i), None); - assert_eq!(map.len(), i + 1); - assert_eq!(map, map.clone()); - } - - for i in 0..size { - assert_eq!(map.insert(i, 100 * i), Some(10 * i)); - assert_eq!(map.len(), size); - assert_eq!(map, map.clone()); - } - - for i in 0..size / 2 { - assert_eq!(map.remove(&(i * 2)), Some(i * 200)); - assert_eq!(map.len(), size - i - 1); - assert_eq!(map, map.clone()); - } - - for i in 0..size / 2 { - assert_eq!(map.remove(&(2 * i)), None); - assert_eq!(map.remove(&(2 * i + 1)), Some(i * 200 + 100)); - assert_eq!(map.len(), size / 2 - i - 1); - assert_eq!(map, map.clone()); - } - - // Test a tree with 2 chock-full levels and a tree with 3 levels. - map = (1..MIN_INSERTS_HEIGHT_2).map(|i| (i, i)).collect(); - assert_eq!(map.len(), MIN_INSERTS_HEIGHT_2 - 1); - assert_eq!(map, map.clone()); - map.insert(0, 0); - assert_eq!(map.len(), MIN_INSERTS_HEIGHT_2); - assert_eq!(map, map.clone()); -} - -#[test] -fn test_clone_from() { - let mut map1 = BTreeMap::new(); - let max_size = MIN_INSERTS_HEIGHT_1; - - // Range to max_size inclusive, because i is the size of map1 being tested. - for i in 0..=max_size { - let mut map2 = BTreeMap::new(); - for j in 0..i { - let mut map1_copy = map2.clone(); - map1_copy.clone_from(&map1); // small cloned from large - assert_eq!(map1_copy, map1); - let mut map2_copy = map1.clone(); - map2_copy.clone_from(&map2); // large cloned from small - assert_eq!(map2_copy, map2); - map2.insert(100 * j + 1, 2 * j + 1); - } - map2.clone_from(&map1); // same length - assert_eq!(map2, map1); - map1.insert(i, 10 * i); - } -} - -#[test] -#[allow(dead_code)] -fn test_variance() { - use std::collections::btree_map::{IntoIter, Iter, Keys, Range, Values}; - - fn map_key<'new>(v: BTreeMap<&'static str, ()>) -> BTreeMap<&'new str, ()> { - v - } - fn map_val<'new>(v: BTreeMap<(), &'static str>) -> BTreeMap<(), &'new str> { - v - } - fn iter_key<'a, 'new>(v: Iter<'a, &'static str, ()>) -> Iter<'a, &'new str, ()> { - v - } - fn iter_val<'a, 'new>(v: Iter<'a, (), &'static str>) -> Iter<'a, (), &'new str> { - v - } - fn into_iter_key<'new>(v: IntoIter<&'static str, ()>) -> IntoIter<&'new str, ()> { - v - } - fn into_iter_val<'new>(v: IntoIter<(), &'static str>) -> IntoIter<(), &'new str> { - v - } - fn range_key<'a, 'new>(v: Range<'a, &'static str, ()>) -> Range<'a, &'new str, ()> { - v - } - fn range_val<'a, 'new>(v: Range<'a, (), &'static str>) -> Range<'a, (), &'new str> { - v - } - fn keys<'a, 'new>(v: Keys<'a, &'static str, ()>) -> Keys<'a, &'new str, ()> { - v - } - fn vals<'a, 'new>(v: Values<'a, (), &'static str>) -> Values<'a, (), &'new str> { - v - } -} - -#[test] -fn test_occupied_entry_key() { - let mut a = BTreeMap::new(); - let key = "hello there"; - let value = "value goes here"; - assert!(a.is_empty()); - a.insert(key.clone(), value.clone()); - assert_eq!(a.len(), 1); - assert_eq!(a[key], value); - - match a.entry(key.clone()) { - Vacant(_) => panic!(), - Occupied(e) => assert_eq!(key, *e.key()), - } - assert_eq!(a.len(), 1); - assert_eq!(a[key], value); -} - -#[test] -fn test_vacant_entry_key() { - let mut a = BTreeMap::new(); - let key = "hello there"; - let value = "value goes here"; - - assert!(a.is_empty()); - match a.entry(key.clone()) { - Occupied(_) => panic!(), - Vacant(e) => { - assert_eq!(key, *e.key()); - e.insert(value.clone()); - } - } - assert_eq!(a.len(), 1); - assert_eq!(a[key], value); -} - -#[test] -fn test_first_last_entry() { - let mut a = BTreeMap::new(); - assert!(a.first_entry().is_none()); - assert!(a.last_entry().is_none()); - a.insert(1, 42); - assert_eq!(a.first_entry().unwrap().key(), &1); - assert_eq!(a.last_entry().unwrap().key(), &1); - a.insert(2, 24); - assert_eq!(a.first_entry().unwrap().key(), &1); - assert_eq!(a.last_entry().unwrap().key(), &2); - a.insert(0, 6); - assert_eq!(a.first_entry().unwrap().key(), &0); - assert_eq!(a.last_entry().unwrap().key(), &2); - let (k1, v1) = a.first_entry().unwrap().remove_entry(); - assert_eq!(k1, 0); - assert_eq!(v1, 6); - let (k2, v2) = a.last_entry().unwrap().remove_entry(); - assert_eq!(k2, 2); - assert_eq!(v2, 24); - assert_eq!(a.first_entry().unwrap().key(), &1); - assert_eq!(a.last_entry().unwrap().key(), &1); -} - -macro_rules! create_append_test { - ($name:ident, $len:expr) => { - #[test] - fn $name() { - let mut a = BTreeMap::new(); - for i in 0..8 { - a.insert(i, i); - } - - let mut b = BTreeMap::new(); - for i in 5..$len { - b.insert(i, 2 * i); - } - - a.append(&mut b); - - assert_eq!(a.len(), $len); - assert_eq!(b.len(), 0); - - for i in 0..$len { - if i < 5 { - assert_eq!(a[&i], i); - } else { - assert_eq!(a[&i], 2 * i); - } - } - - assert_eq!(a.remove(&($len - 1)), Some(2 * ($len - 1))); - assert_eq!(a.insert($len - 1, 20), None); - } - }; -} - -// These are mostly for testing the algorithm that "fixes" the right edge after insertion. -// Single node. -create_append_test!(test_append_9, 9); -// Two leafs that don't need fixing. -create_append_test!(test_append_17, 17); -// Two leafs where the second one ends up underfull and needs stealing at the end. -create_append_test!(test_append_14, 14); -// Two leafs where the second one ends up empty because the insertion finished at the root. -create_append_test!(test_append_12, 12); -// Three levels; insertion finished at the root. -create_append_test!(test_append_144, 144); -// Three levels; insertion finished at leaf while there is an empty node on the second level. -create_append_test!(test_append_145, 145); -// Tests for several randomly chosen sizes. -create_append_test!(test_append_170, 170); -create_append_test!(test_append_181, 181); -#[cfg(not(miri))] // Miri is too slow -create_append_test!(test_append_239, 239); -#[cfg(not(miri))] // Miri is too slow -create_append_test!(test_append_1700, 1700); - -fn rand_data(len: usize) -> Vec<(u32, u32)> { - let mut rng = DeterministicRng::new(); - Vec::from_iter((0..len).map(|_| (rng.next(), rng.next()))) -} - -#[test] -fn test_split_off_empty_right() { - let mut data = rand_data(173); - - let mut map = BTreeMap::from_iter(data.clone()); - let right = map.split_off(&(data.iter().max().unwrap().0 + 1)); - - data.sort(); - assert!(map.into_iter().eq(data)); - assert!(right.into_iter().eq(None)); -} - -#[test] -fn test_split_off_empty_left() { - let mut data = rand_data(314); - - let mut map = BTreeMap::from_iter(data.clone()); - let right = map.split_off(&data.iter().min().unwrap().0); - - data.sort(); - assert!(map.into_iter().eq(None)); - assert!(right.into_iter().eq(data)); -} - -// In a tree with 3 levels, if all but a part of the first leaf node is split off, -// make sure fix_top eliminates both top levels. -#[test] -fn test_split_off_tiny_left_height_2() { - let pairs = (0..MIN_INSERTS_HEIGHT_2).map(|i| (i, i)); - let mut left: BTreeMap<_, _> = pairs.clone().collect(); - let right = left.split_off(&1); - assert_eq!(left.len(), 1); - assert_eq!(right.len(), MIN_INSERTS_HEIGHT_2 - 1); - assert_eq!(*left.first_key_value().unwrap().0, 0); - assert_eq!(*right.first_key_value().unwrap().0, 1); -} - -// In a tree with 3 levels, if only part of the last leaf node is split off, -// make sure fix_top eliminates both top levels. -#[test] -fn test_split_off_tiny_right_height_2() { - let pairs = (0..MIN_INSERTS_HEIGHT_2).map(|i| (i, i)); - let last = MIN_INSERTS_HEIGHT_2 - 1; - let mut left: BTreeMap<_, _> = pairs.clone().collect(); - assert_eq!(*left.last_key_value().unwrap().0, last); - let right = left.split_off(&last); - assert_eq!(left.len(), MIN_INSERTS_HEIGHT_2 - 1); - assert_eq!(right.len(), 1); - assert_eq!(*left.last_key_value().unwrap().0, last - 1); - assert_eq!(*right.last_key_value().unwrap().0, last); -} - -#[test] -fn test_split_off_large_random_sorted() { - // Miri is too slow - let mut data = if cfg!(miri) { rand_data(529) } else { rand_data(1529) }; - // special case with maximum height. - data.sort(); - - let mut map = BTreeMap::from_iter(data.clone()); - let key = data[data.len() / 2].0; - let right = map.split_off(&key); - - assert!(map.into_iter().eq(data.clone().into_iter().filter(|x| x.0 < key))); - assert!(right.into_iter().eq(data.into_iter().filter(|x| x.0 >= key))); -} - -#[test] -fn test_into_iter_drop_leak_height_0() { - static DROPS: AtomicUsize = AtomicUsize::new(0); - - struct D; - - impl Drop for D { - fn drop(&mut self) { - if DROPS.fetch_add(1, Ordering::SeqCst) == 3 { - panic!("panic in `drop`"); - } - } - } - - let mut map = BTreeMap::new(); - map.insert("a", D); - map.insert("b", D); - map.insert("c", D); - map.insert("d", D); - map.insert("e", D); - - catch_unwind(move || drop(map.into_iter())).unwrap_err(); - - assert_eq!(DROPS.load(Ordering::SeqCst), 5); -} - -#[test] -fn test_into_iter_drop_leak_height_1() { - let size = MIN_INSERTS_HEIGHT_1; - static DROPS: AtomicUsize = AtomicUsize::new(0); - static PANIC_POINT: AtomicUsize = AtomicUsize::new(0); - - struct D; - impl Drop for D { - fn drop(&mut self) { - if DROPS.fetch_add(1, Ordering::SeqCst) == PANIC_POINT.load(Ordering::SeqCst) { - panic!("panic in `drop`"); - } - } - } - - for panic_point in vec![0, 1, size - 2, size - 1] { - DROPS.store(0, Ordering::SeqCst); - PANIC_POINT.store(panic_point, Ordering::SeqCst); - let map: BTreeMap<_, _> = (0..size).map(|i| (i, D)).collect(); - catch_unwind(move || drop(map.into_iter())).unwrap_err(); - assert_eq!(DROPS.load(Ordering::SeqCst), size); - } -} diff --git a/src/liballoc/tests/btree/mod.rs b/src/liballoc/tests/btree/mod.rs deleted file mode 100644 index 1d08ae13e05..00000000000 --- a/src/liballoc/tests/btree/mod.rs +++ /dev/null @@ -1,27 +0,0 @@ -mod map; -mod set; - -/// XorShiftRng -struct DeterministicRng { - x: u32, - y: u32, - z: u32, - w: u32, -} - -impl DeterministicRng { - fn new() -> Self { - DeterministicRng { x: 0x193a6754, y: 0xa8a7d469, z: 0x97830e05, w: 0x113ba7bb } - } - - fn next(&mut self) -> u32 { - let x = self.x; - let t = x ^ (x << 11); - self.x = self.y; - self.y = self.z; - self.z = self.w; - let w_ = self.w; - self.w = w_ ^ (w_ >> 19) ^ (t ^ (t >> 8)); - self.w - } -} diff --git a/src/liballoc/tests/btree/set.rs b/src/liballoc/tests/btree/set.rs deleted file mode 100644 index b6c34b7c6c3..00000000000 --- a/src/liballoc/tests/btree/set.rs +++ /dev/null @@ -1,666 +0,0 @@ -use std::collections::BTreeSet; -use std::iter::FromIterator; -use std::panic::{catch_unwind, AssertUnwindSafe}; -use std::sync::atomic::{AtomicU32, Ordering}; - -use super::DeterministicRng; - -#[test] -fn test_clone_eq() { - let mut m = BTreeSet::new(); - - m.insert(1); - m.insert(2); - - assert_eq!(m.clone(), m); -} - -#[test] -fn test_hash() { - use crate::hash; - - let mut x = BTreeSet::new(); - let mut y = BTreeSet::new(); - - x.insert(1); - x.insert(2); - x.insert(3); - - y.insert(3); - y.insert(2); - y.insert(1); - - assert_eq!(hash(&x), hash(&y)); -} - -#[test] -fn test_iter_min_max() { - let mut a = BTreeSet::new(); - assert_eq!(a.iter().min(), None); - assert_eq!(a.iter().max(), None); - assert_eq!(a.range(..).min(), None); - assert_eq!(a.range(..).max(), None); - assert_eq!(a.difference(&BTreeSet::new()).min(), None); - assert_eq!(a.difference(&BTreeSet::new()).max(), None); - assert_eq!(a.intersection(&a).min(), None); - assert_eq!(a.intersection(&a).max(), None); - assert_eq!(a.symmetric_difference(&BTreeSet::new()).min(), None); - assert_eq!(a.symmetric_difference(&BTreeSet::new()).max(), None); - assert_eq!(a.union(&a).min(), None); - assert_eq!(a.union(&a).max(), None); - a.insert(1); - a.insert(2); - assert_eq!(a.iter().min(), Some(&1)); - assert_eq!(a.iter().max(), Some(&2)); - assert_eq!(a.range(..).min(), Some(&1)); - assert_eq!(a.range(..).max(), Some(&2)); - assert_eq!(a.difference(&BTreeSet::new()).min(), Some(&1)); - assert_eq!(a.difference(&BTreeSet::new()).max(), Some(&2)); - assert_eq!(a.intersection(&a).min(), Some(&1)); - assert_eq!(a.intersection(&a).max(), Some(&2)); - assert_eq!(a.symmetric_difference(&BTreeSet::new()).min(), Some(&1)); - assert_eq!(a.symmetric_difference(&BTreeSet::new()).max(), Some(&2)); - assert_eq!(a.union(&a).min(), Some(&1)); - assert_eq!(a.union(&a).max(), Some(&2)); -} - -fn check<F>(a: &[i32], b: &[i32], expected: &[i32], f: F) -where - F: FnOnce(&BTreeSet<i32>, &BTreeSet<i32>, &mut dyn FnMut(&i32) -> bool) -> bool, -{ - let mut set_a = BTreeSet::new(); - let mut set_b = BTreeSet::new(); - - for x in a { - assert!(set_a.insert(*x)) - } - for y in b { - assert!(set_b.insert(*y)) - } - - let mut i = 0; - f(&set_a, &set_b, &mut |&x| { - if i < expected.len() { - assert_eq!(x, expected[i]); - } - i += 1; - true - }); - assert_eq!(i, expected.len()); -} - -#[test] -fn test_intersection() { - fn check_intersection(a: &[i32], b: &[i32], expected: &[i32]) { - check(a, b, expected, |x, y, f| x.intersection(y).all(f)) - } - - check_intersection(&[], &[], &[]); - check_intersection(&[1, 2, 3], &[], &[]); - check_intersection(&[], &[1, 2, 3], &[]); - check_intersection(&[2], &[1, 2, 3], &[2]); - check_intersection(&[1, 2, 3], &[2], &[2]); - check_intersection(&[11, 1, 3, 77, 103, 5, -5], &[2, 11, 77, -9, -42, 5, 3], &[3, 5, 11, 77]); - - if cfg!(miri) { - // Miri is too slow - return; - } - - let large = (0..100).collect::<Vec<_>>(); - check_intersection(&[], &large, &[]); - check_intersection(&large, &[], &[]); - check_intersection(&[-1], &large, &[]); - check_intersection(&large, &[-1], &[]); - check_intersection(&[0], &large, &[0]); - check_intersection(&large, &[0], &[0]); - check_intersection(&[99], &large, &[99]); - check_intersection(&large, &[99], &[99]); - check_intersection(&[100], &large, &[]); - check_intersection(&large, &[100], &[]); - check_intersection(&[11, 5000, 1, 3, 77, 8924], &large, &[1, 3, 11, 77]); -} - -#[test] -fn test_intersection_size_hint() { - let x: BTreeSet<i32> = [3, 4].iter().copied().collect(); - let y: BTreeSet<i32> = [1, 2, 3].iter().copied().collect(); - let mut iter = x.intersection(&y); - assert_eq!(iter.size_hint(), (1, Some(1))); - assert_eq!(iter.next(), Some(&3)); - assert_eq!(iter.size_hint(), (0, Some(0))); - assert_eq!(iter.next(), None); - - iter = y.intersection(&y); - assert_eq!(iter.size_hint(), (0, Some(3))); - assert_eq!(iter.next(), Some(&1)); - assert_eq!(iter.size_hint(), (0, Some(2))); -} - -#[test] -fn test_difference() { - fn check_difference(a: &[i32], b: &[i32], expected: &[i32]) { - check(a, b, expected, |x, y, f| x.difference(y).all(f)) - } - - check_difference(&[], &[], &[]); - check_difference(&[1, 12], &[], &[1, 12]); - check_difference(&[], &[1, 2, 3, 9], &[]); - check_difference(&[1, 3, 5, 9, 11], &[3, 9], &[1, 5, 11]); - check_difference(&[1, 3, 5, 9, 11], &[3, 6, 9], &[1, 5, 11]); - check_difference(&[1, 3, 5, 9, 11], &[0, 1], &[3, 5, 9, 11]); - check_difference(&[1, 3, 5, 9, 11], &[11, 12], &[1, 3, 5, 9]); - check_difference( - &[-5, 11, 22, 33, 40, 42], - &[-12, -5, 14, 23, 34, 38, 39, 50], - &[11, 22, 33, 40, 42], - ); - - if cfg!(miri) { - // Miri is too slow - return; - } - - let large = (0..100).collect::<Vec<_>>(); - check_difference(&[], &large, &[]); - check_difference(&[-1], &large, &[-1]); - check_difference(&[0], &large, &[]); - check_difference(&[99], &large, &[]); - check_difference(&[100], &large, &[100]); - check_difference(&[11, 5000, 1, 3, 77, 8924], &large, &[5000, 8924]); - check_difference(&large, &[], &large); - check_difference(&large, &[-1], &large); - check_difference(&large, &[100], &large); -} - -#[test] -fn test_difference_size_hint() { - let s246: BTreeSet<i32> = [2, 4, 6].iter().copied().collect(); - let s23456: BTreeSet<i32> = (2..=6).collect(); - let mut iter = s246.difference(&s23456); - assert_eq!(iter.size_hint(), (0, Some(3))); - assert_eq!(iter.next(), None); - - let s12345: BTreeSet<i32> = (1..=5).collect(); - iter = s246.difference(&s12345); - assert_eq!(iter.size_hint(), (0, Some(3))); - assert_eq!(iter.next(), Some(&6)); - assert_eq!(iter.size_hint(), (0, Some(0))); - assert_eq!(iter.next(), None); - - let s34567: BTreeSet<i32> = (3..=7).collect(); - iter = s246.difference(&s34567); - assert_eq!(iter.size_hint(), (0, Some(3))); - assert_eq!(iter.next(), Some(&2)); - assert_eq!(iter.size_hint(), (0, Some(2))); - assert_eq!(iter.next(), None); - - let s1: BTreeSet<i32> = (-9..=1).collect(); - iter = s246.difference(&s1); - assert_eq!(iter.size_hint(), (3, Some(3))); - - let s2: BTreeSet<i32> = (-9..=2).collect(); - iter = s246.difference(&s2); - assert_eq!(iter.size_hint(), (2, Some(2))); - assert_eq!(iter.next(), Some(&4)); - assert_eq!(iter.size_hint(), (1, Some(1))); - - let s23: BTreeSet<i32> = (2..=3).collect(); - iter = s246.difference(&s23); - assert_eq!(iter.size_hint(), (1, Some(3))); - assert_eq!(iter.next(), Some(&4)); - assert_eq!(iter.size_hint(), (1, Some(1))); - - let s4: BTreeSet<i32> = (4..=4).collect(); - iter = s246.difference(&s4); - assert_eq!(iter.size_hint(), (2, Some(3))); - assert_eq!(iter.next(), Some(&2)); - assert_eq!(iter.size_hint(), (1, Some(2))); - assert_eq!(iter.next(), Some(&6)); - assert_eq!(iter.size_hint(), (0, Some(0))); - assert_eq!(iter.next(), None); - - let s56: BTreeSet<i32> = (5..=6).collect(); - iter = s246.difference(&s56); - assert_eq!(iter.size_hint(), (1, Some(3))); - assert_eq!(iter.next(), Some(&2)); - assert_eq!(iter.size_hint(), (0, Some(2))); - - let s6: BTreeSet<i32> = (6..=19).collect(); - iter = s246.difference(&s6); - assert_eq!(iter.size_hint(), (2, Some(2))); - assert_eq!(iter.next(), Some(&2)); - assert_eq!(iter.size_hint(), (1, Some(1))); - - let s7: BTreeSet<i32> = (7..=19).collect(); - iter = s246.difference(&s7); - assert_eq!(iter.size_hint(), (3, Some(3))); -} - -#[test] -fn test_symmetric_difference() { - fn check_symmetric_difference(a: &[i32], b: &[i32], expected: &[i32]) { - check(a, b, expected, |x, y, f| x.symmetric_difference(y).all(f)) - } - - check_symmetric_difference(&[], &[], &[]); - check_symmetric_difference(&[1, 2, 3], &[2], &[1, 3]); - check_symmetric_difference(&[2], &[1, 2, 3], &[1, 3]); - check_symmetric_difference(&[1, 3, 5, 9, 11], &[-2, 3, 9, 14, 22], &[-2, 1, 5, 11, 14, 22]); -} - -#[test] -fn test_symmetric_difference_size_hint() { - let x: BTreeSet<i32> = [2, 4].iter().copied().collect(); - let y: BTreeSet<i32> = [1, 2, 3].iter().copied().collect(); - let mut iter = x.symmetric_difference(&y); - assert_eq!(iter.size_hint(), (0, Some(5))); - assert_eq!(iter.next(), Some(&1)); - assert_eq!(iter.size_hint(), (0, Some(4))); - assert_eq!(iter.next(), Some(&3)); - assert_eq!(iter.size_hint(), (0, Some(1))); -} - -#[test] -fn test_union() { - fn check_union(a: &[i32], b: &[i32], expected: &[i32]) { - check(a, b, expected, |x, y, f| x.union(y).all(f)) - } - - check_union(&[], &[], &[]); - check_union(&[1, 2, 3], &[2], &[1, 2, 3]); - check_union(&[2], &[1, 2, 3], &[1, 2, 3]); - check_union( - &[1, 3, 5, 9, 11, 16, 19, 24], - &[-2, 1, 5, 9, 13, 19], - &[-2, 1, 3, 5, 9, 11, 13, 16, 19, 24], - ); -} - -#[test] -fn test_union_size_hint() { - let x: BTreeSet<i32> = [2, 4].iter().copied().collect(); - let y: BTreeSet<i32> = [1, 2, 3].iter().copied().collect(); - let mut iter = x.union(&y); - assert_eq!(iter.size_hint(), (3, Some(5))); - assert_eq!(iter.next(), Some(&1)); - assert_eq!(iter.size_hint(), (2, Some(4))); - assert_eq!(iter.next(), Some(&2)); - assert_eq!(iter.size_hint(), (1, Some(2))); -} - -#[test] -// Only tests the simple function definition with respect to intersection -fn test_is_disjoint() { - let one = [1].iter().collect::<BTreeSet<_>>(); - let two = [2].iter().collect::<BTreeSet<_>>(); - assert!(one.is_disjoint(&two)); -} - -#[test] -// Also implicitly tests the trivial function definition of is_superset -fn test_is_subset() { - fn is_subset(a: &[i32], b: &[i32]) -> bool { - let set_a = a.iter().collect::<BTreeSet<_>>(); - let set_b = b.iter().collect::<BTreeSet<_>>(); - set_a.is_subset(&set_b) - } - - assert_eq!(is_subset(&[], &[]), true); - assert_eq!(is_subset(&[], &[1, 2]), true); - assert_eq!(is_subset(&[0], &[1, 2]), false); - assert_eq!(is_subset(&[1], &[1, 2]), true); - assert_eq!(is_subset(&[2], &[1, 2]), true); - assert_eq!(is_subset(&[3], &[1, 2]), false); - assert_eq!(is_subset(&[1, 2], &[1]), false); - assert_eq!(is_subset(&[1, 2], &[1, 2]), true); - assert_eq!(is_subset(&[1, 2], &[2, 3]), false); - assert_eq!( - is_subset(&[-5, 11, 22, 33, 40, 42], &[-12, -5, 11, 14, 22, 23, 33, 34, 38, 39, 40, 42]), - true - ); - assert_eq!(is_subset(&[-5, 11, 22, 33, 40, 42], &[-12, -5, 11, 14, 22, 23, 34, 38]), false); - - if cfg!(miri) { - // Miri is too slow - return; - } - - let large = (0..100).collect::<Vec<_>>(); - assert_eq!(is_subset(&[], &large), true); - assert_eq!(is_subset(&large, &[]), false); - assert_eq!(is_subset(&[-1], &large), false); - assert_eq!(is_subset(&[0], &large), true); - assert_eq!(is_subset(&[1, 2], &large), true); - assert_eq!(is_subset(&[99, 100], &large), false); -} - -#[test] -fn test_drain_filter() { - let mut x: BTreeSet<_> = [1].iter().copied().collect(); - let mut y: BTreeSet<_> = [1].iter().copied().collect(); - - x.drain_filter(|_| true); - y.drain_filter(|_| false); - assert_eq!(x.len(), 0); - assert_eq!(y.len(), 1); -} - -#[test] -fn test_drain_filter_drop_panic_leak() { - static PREDS: AtomicU32 = AtomicU32::new(0); - static DROPS: AtomicU32 = AtomicU32::new(0); - - #[derive(PartialEq, Eq, PartialOrd, Ord)] - struct D(i32); - impl Drop for D { - fn drop(&mut self) { - if DROPS.fetch_add(1, Ordering::SeqCst) == 1 { - panic!("panic in `drop`"); - } - } - } - - let mut set = BTreeSet::new(); - set.insert(D(0)); - set.insert(D(4)); - set.insert(D(8)); - - catch_unwind(move || { - drop(set.drain_filter(|d| { - PREDS.fetch_add(1u32 << d.0, Ordering::SeqCst); - true - })) - }) - .ok(); - - assert_eq!(PREDS.load(Ordering::SeqCst), 0x011); - assert_eq!(DROPS.load(Ordering::SeqCst), 3); -} - -#[test] -fn test_drain_filter_pred_panic_leak() { - static PREDS: AtomicU32 = AtomicU32::new(0); - static DROPS: AtomicU32 = AtomicU32::new(0); - - #[derive(PartialEq, Eq, PartialOrd, Ord)] - struct D(i32); - impl Drop for D { - fn drop(&mut self) { - DROPS.fetch_add(1, Ordering::SeqCst); - } - } - - let mut set = BTreeSet::new(); - set.insert(D(0)); - set.insert(D(4)); - set.insert(D(8)); - - catch_unwind(AssertUnwindSafe(|| { - drop(set.drain_filter(|d| { - PREDS.fetch_add(1u32 << d.0, Ordering::SeqCst); - match d.0 { - 0 => true, - _ => panic!(), - } - })) - })) - .ok(); - - assert_eq!(PREDS.load(Ordering::SeqCst), 0x011); - assert_eq!(DROPS.load(Ordering::SeqCst), 1); - assert_eq!(set.len(), 2); - assert_eq!(set.first().unwrap().0, 4); - assert_eq!(set.last().unwrap().0, 8); -} - -#[test] -fn test_clear() { - let mut x = BTreeSet::new(); - x.insert(1); - - x.clear(); - assert!(x.is_empty()); -} - -#[test] -fn test_zip() { - let mut x = BTreeSet::new(); - x.insert(5); - x.insert(12); - x.insert(11); - - let mut y = BTreeSet::new(); - y.insert("foo"); - y.insert("bar"); - - let x = x; - let y = y; - let mut z = x.iter().zip(&y); - - assert_eq!(z.next().unwrap(), (&5, &("bar"))); - assert_eq!(z.next().unwrap(), (&11, &("foo"))); - assert!(z.next().is_none()); -} - -#[test] -fn test_from_iter() { - let xs = [1, 2, 3, 4, 5, 6, 7, 8, 9]; - - let set: BTreeSet<_> = xs.iter().cloned().collect(); - - for x in &xs { - assert!(set.contains(x)); - } -} - -#[test] -fn test_show() { - let mut set = BTreeSet::new(); - let empty = BTreeSet::<i32>::new(); - - set.insert(1); - set.insert(2); - - let set_str = format!("{:?}", set); - - assert_eq!(set_str, "{1, 2}"); - assert_eq!(format!("{:?}", empty), "{}"); -} - -#[test] -fn test_extend_ref() { - let mut a = BTreeSet::new(); - a.insert(1); - - a.extend(&[2, 3, 4]); - - assert_eq!(a.len(), 4); - assert!(a.contains(&1)); - assert!(a.contains(&2)); - assert!(a.contains(&3)); - assert!(a.contains(&4)); - - let mut b = BTreeSet::new(); - b.insert(5); - b.insert(6); - - a.extend(&b); - - assert_eq!(a.len(), 6); - assert!(a.contains(&1)); - assert!(a.contains(&2)); - assert!(a.contains(&3)); - assert!(a.contains(&4)); - assert!(a.contains(&5)); - assert!(a.contains(&6)); -} - -#[test] -fn test_recovery() { - use std::cmp::Ordering; - - #[derive(Debug)] - struct Foo(&'static str, i32); - - impl PartialEq for Foo { - fn eq(&self, other: &Self) -> bool { - self.0 == other.0 - } - } - - impl Eq for Foo {} - - impl PartialOrd for Foo { - fn partial_cmp(&self, other: &Self) -> Option<Ordering> { - self.0.partial_cmp(&other.0) - } - } - - impl Ord for Foo { - fn cmp(&self, other: &Self) -> Ordering { - self.0.cmp(&other.0) - } - } - - let mut s = BTreeSet::new(); - assert_eq!(s.replace(Foo("a", 1)), None); - assert_eq!(s.len(), 1); - assert_eq!(s.replace(Foo("a", 2)), Some(Foo("a", 1))); - assert_eq!(s.len(), 1); - - { - let mut it = s.iter(); - assert_eq!(it.next(), Some(&Foo("a", 2))); - assert_eq!(it.next(), None); - } - - assert_eq!(s.get(&Foo("a", 1)), Some(&Foo("a", 2))); - assert_eq!(s.take(&Foo("a", 1)), Some(Foo("a", 2))); - assert_eq!(s.len(), 0); - - assert_eq!(s.get(&Foo("a", 1)), None); - assert_eq!(s.take(&Foo("a", 1)), None); - - assert_eq!(s.iter().next(), None); -} - -#[test] -#[allow(dead_code)] -fn test_variance() { - use std::collections::btree_set::{IntoIter, Iter, Range}; - - fn set<'new>(v: BTreeSet<&'static str>) -> BTreeSet<&'new str> { - v - } - fn iter<'a, 'new>(v: Iter<'a, &'static str>) -> Iter<'a, &'new str> { - v - } - fn into_iter<'new>(v: IntoIter<&'static str>) -> IntoIter<&'new str> { - v - } - fn range<'a, 'new>(v: Range<'a, &'static str>) -> Range<'a, &'new str> { - v - } -} - -#[test] -fn test_append() { - let mut a = BTreeSet::new(); - a.insert(1); - a.insert(2); - a.insert(3); - - let mut b = BTreeSet::new(); - b.insert(3); - b.insert(4); - b.insert(5); - - a.append(&mut b); - - assert_eq!(a.len(), 5); - assert_eq!(b.len(), 0); - - assert_eq!(a.contains(&1), true); - assert_eq!(a.contains(&2), true); - assert_eq!(a.contains(&3), true); - assert_eq!(a.contains(&4), true); - assert_eq!(a.contains(&5), true); -} - -#[test] -fn test_first_last() { - let mut a = BTreeSet::new(); - assert_eq!(a.first(), None); - assert_eq!(a.last(), None); - a.insert(1); - assert_eq!(a.first(), Some(&1)); - assert_eq!(a.last(), Some(&1)); - a.insert(2); - assert_eq!(a.first(), Some(&1)); - assert_eq!(a.last(), Some(&2)); - for i in 3..=12 { - a.insert(i); - } - assert_eq!(a.first(), Some(&1)); - assert_eq!(a.last(), Some(&12)); - assert_eq!(a.pop_first(), Some(1)); - assert_eq!(a.pop_last(), Some(12)); - assert_eq!(a.pop_first(), Some(2)); - assert_eq!(a.pop_last(), Some(11)); - assert_eq!(a.pop_first(), Some(3)); - assert_eq!(a.pop_last(), Some(10)); - assert_eq!(a.pop_first(), Some(4)); - assert_eq!(a.pop_first(), Some(5)); - assert_eq!(a.pop_first(), Some(6)); - assert_eq!(a.pop_first(), Some(7)); - assert_eq!(a.pop_first(), Some(8)); - assert_eq!(a.clone().pop_last(), Some(9)); - assert_eq!(a.pop_first(), Some(9)); - assert_eq!(a.pop_first(), None); - assert_eq!(a.pop_last(), None); -} - -fn rand_data(len: usize) -> Vec<u32> { - let mut rng = DeterministicRng::new(); - Vec::from_iter((0..len).map(|_| rng.next())) -} - -#[test] -fn test_split_off_empty_right() { - let mut data = rand_data(173); - - let mut set = BTreeSet::from_iter(data.clone()); - let right = set.split_off(&(data.iter().max().unwrap() + 1)); - - data.sort(); - assert!(set.into_iter().eq(data)); - assert!(right.into_iter().eq(None)); -} - -#[test] -fn test_split_off_empty_left() { - let mut data = rand_data(314); - - let mut set = BTreeSet::from_iter(data.clone()); - let right = set.split_off(data.iter().min().unwrap()); - - data.sort(); - assert!(set.into_iter().eq(None)); - assert!(right.into_iter().eq(data)); -} - -#[test] -fn test_split_off_large_random_sorted() { - // Miri is too slow - let mut data = if cfg!(miri) { rand_data(529) } else { rand_data(1529) }; - // special case with maximum height. - data.sort(); - - let mut set = BTreeSet::from_iter(data.clone()); - let key = data[data.len() / 2]; - let right = set.split_off(&key); - - assert!(set.into_iter().eq(data.clone().into_iter().filter(|x| *x < key))); - assert!(right.into_iter().eq(data.into_iter().filter(|x| *x >= key))); -} diff --git a/src/liballoc/tests/cow_str.rs b/src/liballoc/tests/cow_str.rs deleted file mode 100644 index 62a5c245a54..00000000000 --- a/src/liballoc/tests/cow_str.rs +++ /dev/null @@ -1,144 +0,0 @@ -use std::borrow::Cow; - -// check that Cow<'a, str> implements addition -#[test] -fn check_cow_add_cow() { - let borrowed1 = Cow::Borrowed("Hello, "); - let borrowed2 = Cow::Borrowed("World!"); - let borrow_empty = Cow::Borrowed(""); - - let owned1: Cow<'_, str> = Cow::Owned(String::from("Hi, ")); - let owned2: Cow<'_, str> = Cow::Owned(String::from("Rustaceans!")); - let owned_empty: Cow<'_, str> = Cow::Owned(String::new()); - - assert_eq!("Hello, World!", borrowed1.clone() + borrowed2.clone()); - assert_eq!("Hello, Rustaceans!", borrowed1.clone() + owned2.clone()); - - assert_eq!("Hi, World!", owned1.clone() + borrowed2.clone()); - assert_eq!("Hi, Rustaceans!", owned1.clone() + owned2.clone()); - - if let Cow::Owned(_) = borrowed1.clone() + borrow_empty.clone() { - panic!("Adding empty strings to a borrow should note allocate"); - } - if let Cow::Owned(_) = borrow_empty.clone() + borrowed1.clone() { - panic!("Adding empty strings to a borrow should note allocate"); - } - if let Cow::Owned(_) = borrowed1.clone() + owned_empty.clone() { - panic!("Adding empty strings to a borrow should note allocate"); - } - if let Cow::Owned(_) = owned_empty.clone() + borrowed1.clone() { - panic!("Adding empty strings to a borrow should note allocate"); - } -} - -#[test] -fn check_cow_add_str() { - let borrowed = Cow::Borrowed("Hello, "); - let borrow_empty = Cow::Borrowed(""); - - let owned: Cow<'_, str> = Cow::Owned(String::from("Hi, ")); - let owned_empty: Cow<'_, str> = Cow::Owned(String::new()); - - assert_eq!("Hello, World!", borrowed.clone() + "World!"); - - assert_eq!("Hi, World!", owned.clone() + "World!"); - - if let Cow::Owned(_) = borrowed.clone() + "" { - panic!("Adding empty strings to a borrow should note allocate"); - } - if let Cow::Owned(_) = borrow_empty.clone() + "Hello, " { - panic!("Adding empty strings to a borrow should note allocate"); - } - if let Cow::Owned(_) = owned_empty.clone() + "Hello, " { - panic!("Adding empty strings to a borrow should note allocate"); - } -} - -#[test] -fn check_cow_add_assign_cow() { - let mut borrowed1 = Cow::Borrowed("Hello, "); - let borrowed2 = Cow::Borrowed("World!"); - let borrow_empty = Cow::Borrowed(""); - - let mut owned1: Cow<'_, str> = Cow::Owned(String::from("Hi, ")); - let owned2: Cow<'_, str> = Cow::Owned(String::from("Rustaceans!")); - let owned_empty: Cow<'_, str> = Cow::Owned(String::new()); - - let mut s = borrowed1.clone(); - s += borrow_empty.clone(); - assert_eq!("Hello, ", s); - if let Cow::Owned(_) = s { - panic!("Adding empty strings to a borrow should note allocate"); - } - let mut s = borrow_empty.clone(); - s += borrowed1.clone(); - assert_eq!("Hello, ", s); - if let Cow::Owned(_) = s { - panic!("Adding empty strings to a borrow should note allocate"); - } - let mut s = borrowed1.clone(); - s += owned_empty.clone(); - assert_eq!("Hello, ", s); - if let Cow::Owned(_) = s { - panic!("Adding empty strings to a borrow should note allocate"); - } - let mut s = owned_empty.clone(); - s += borrowed1.clone(); - assert_eq!("Hello, ", s); - if let Cow::Owned(_) = s { - panic!("Adding empty strings to a borrow should note allocate"); - } - - owned1 += borrowed2; - borrowed1 += owned2; - - assert_eq!("Hi, World!", owned1); - assert_eq!("Hello, Rustaceans!", borrowed1); -} - -#[test] -fn check_cow_add_assign_str() { - let mut borrowed = Cow::Borrowed("Hello, "); - let borrow_empty = Cow::Borrowed(""); - - let mut owned: Cow<'_, str> = Cow::Owned(String::from("Hi, ")); - let owned_empty: Cow<'_, str> = Cow::Owned(String::new()); - - let mut s = borrowed.clone(); - s += ""; - assert_eq!("Hello, ", s); - if let Cow::Owned(_) = s { - panic!("Adding empty strings to a borrow should note allocate"); - } - let mut s = borrow_empty.clone(); - s += "World!"; - assert_eq!("World!", s); - if let Cow::Owned(_) = s { - panic!("Adding empty strings to a borrow should note allocate"); - } - let mut s = owned_empty.clone(); - s += "World!"; - assert_eq!("World!", s); - if let Cow::Owned(_) = s { - panic!("Adding empty strings to a borrow should note allocate"); - } - - owned += "World!"; - borrowed += "World!"; - - assert_eq!("Hi, World!", owned); - assert_eq!("Hello, World!", borrowed); -} - -#[test] -fn check_cow_clone_from() { - let mut c1: Cow<'_, str> = Cow::Owned(String::with_capacity(25)); - let s: String = "hi".to_string(); - assert!(s.capacity() < 25); - let c2: Cow<'_, str> = Cow::Owned(s); - c1.clone_from(&c2); - assert!(c1.into_owned().capacity() >= 25); - let mut c3: Cow<'_, str> = Cow::Borrowed("bye"); - c3.clone_from(&c2); - assert_eq!(c2, c3); -} diff --git a/src/liballoc/tests/fmt.rs b/src/liballoc/tests/fmt.rs deleted file mode 100644 index 0ad092b4997..00000000000 --- a/src/liballoc/tests/fmt.rs +++ /dev/null @@ -1,7 +0,0 @@ -use std::fmt; - -#[test] -fn test_format() { - let s = fmt::format(format_args!("Hello, {}!", "world")); - assert_eq!(s, "Hello, world!"); -} diff --git a/src/liballoc/tests/heap.rs b/src/liballoc/tests/heap.rs deleted file mode 100644 index 62f062b83d7..00000000000 --- a/src/liballoc/tests/heap.rs +++ /dev/null @@ -1,47 +0,0 @@ -use std::alloc::{AllocInit, AllocRef, Global, Layout, System}; - -/// Issue #45955 and #62251. -#[test] -fn alloc_system_overaligned_request() { - check_overalign_requests(System) -} - -#[test] -fn std_heap_overaligned_request() { - check_overalign_requests(Global) -} - -fn check_overalign_requests<T: AllocRef>(mut allocator: T) { - for &align in &[4, 8, 16, 32] { - // less than and bigger than `MIN_ALIGN` - for &size in &[align / 2, align - 1] { - // size less than alignment - let iterations = 128; - unsafe { - let pointers: Vec<_> = (0..iterations) - .map(|_| { - allocator - .alloc( - Layout::from_size_align(size, align).unwrap(), - AllocInit::Uninitialized, - ) - .unwrap() - .ptr - }) - .collect(); - for &ptr in &pointers { - assert_eq!( - (ptr.as_ptr() as usize) % align, - 0, - "Got a pointer less aligned than requested" - ) - } - - // Clean up - for &ptr in &pointers { - allocator.dealloc(ptr, Layout::from_size_align(size, align).unwrap()) - } - } - } - } -} diff --git a/src/liballoc/tests/lib.rs b/src/liballoc/tests/lib.rs deleted file mode 100644 index e2dc816b015..00000000000 --- a/src/liballoc/tests/lib.rs +++ /dev/null @@ -1,57 +0,0 @@ -#![feature(allocator_api)] -#![feature(box_syntax)] -#![feature(btree_drain_filter)] -#![feature(drain_filter)] -#![feature(exact_size_is_empty)] -#![feature(map_first_last)] -#![feature(new_uninit)] -#![feature(pattern)] -#![feature(trusted_len)] -#![feature(try_reserve)] -#![feature(unboxed_closures)] -#![feature(associated_type_bounds)] -#![feature(binary_heap_into_iter_sorted)] -#![feature(binary_heap_drain_sorted)] -#![feature(split_inclusive)] -#![feature(binary_heap_retain)] - -use std::collections::hash_map::DefaultHasher; -use std::hash::{Hash, Hasher}; - -mod arc; -mod binary_heap; -mod borrow; -mod boxed; -mod btree; -mod cow_str; -mod fmt; -mod heap; -mod linked_list; -mod rc; -mod slice; -mod str; -mod string; -mod vec; -mod vec_deque; - -fn hash<T: Hash>(t: &T) -> u64 { - let mut s = DefaultHasher::new(); - t.hash(&mut s); - s.finish() -} - -// FIXME: Instantiated functions with i128 in the signature is not supported in Emscripten. -// See https://github.com/kripken/emscripten-fastcomp/issues/169 -#[cfg(not(target_os = "emscripten"))] -#[test] -fn test_boxed_hasher() { - let ordinary_hash = hash(&5u32); - - let mut hasher_1 = Box::new(DefaultHasher::new()); - 5u32.hash(&mut hasher_1); - assert_eq!(ordinary_hash, hasher_1.finish()); - - let mut hasher_2 = Box::new(DefaultHasher::new()) as Box<dyn Hasher>; - 5u32.hash(&mut hasher_2); - assert_eq!(ordinary_hash, hasher_2.finish()); -} diff --git a/src/liballoc/tests/linked_list.rs b/src/liballoc/tests/linked_list.rs deleted file mode 100644 index afcb9e03fd0..00000000000 --- a/src/liballoc/tests/linked_list.rs +++ /dev/null @@ -1,705 +0,0 @@ -use std::collections::LinkedList; -use std::panic::{catch_unwind, AssertUnwindSafe}; - -#[test] -fn test_basic() { - let mut m = LinkedList::<Box<_>>::new(); - assert_eq!(m.pop_front(), None); - assert_eq!(m.pop_back(), None); - assert_eq!(m.pop_front(), None); - m.push_front(box 1); - assert_eq!(m.pop_front(), Some(box 1)); - m.push_back(box 2); - m.push_back(box 3); - assert_eq!(m.len(), 2); - assert_eq!(m.pop_front(), Some(box 2)); - assert_eq!(m.pop_front(), Some(box 3)); - assert_eq!(m.len(), 0); - assert_eq!(m.pop_front(), None); - m.push_back(box 1); - m.push_back(box 3); - m.push_back(box 5); - m.push_back(box 7); - assert_eq!(m.pop_front(), Some(box 1)); - - let mut n = LinkedList::new(); - n.push_front(2); - n.push_front(3); - { - assert_eq!(n.front().unwrap(), &3); - let x = n.front_mut().unwrap(); - assert_eq!(*x, 3); - *x = 0; - } - { - assert_eq!(n.back().unwrap(), &2); - let y = n.back_mut().unwrap(); - assert_eq!(*y, 2); - *y = 1; - } - assert_eq!(n.pop_front(), Some(0)); - assert_eq!(n.pop_front(), Some(1)); -} - -fn generate_test() -> LinkedList<i32> { - list_from(&[0, 1, 2, 3, 4, 5, 6]) -} - -fn list_from<T: Clone>(v: &[T]) -> LinkedList<T> { - v.iter().cloned().collect() -} - -#[test] -fn test_split_off() { - // singleton - { - let mut m = LinkedList::new(); - m.push_back(1); - - let p = m.split_off(0); - assert_eq!(m.len(), 0); - assert_eq!(p.len(), 1); - assert_eq!(p.back(), Some(&1)); - assert_eq!(p.front(), Some(&1)); - } - - // not singleton, forwards - { - let u = vec![1, 2, 3, 4, 5]; - let mut m = list_from(&u); - let mut n = m.split_off(2); - assert_eq!(m.len(), 2); - assert_eq!(n.len(), 3); - for elt in 1..3 { - assert_eq!(m.pop_front(), Some(elt)); - } - for elt in 3..6 { - assert_eq!(n.pop_front(), Some(elt)); - } - } - // not singleton, backwards - { - let u = vec![1, 2, 3, 4, 5]; - let mut m = list_from(&u); - let mut n = m.split_off(4); - assert_eq!(m.len(), 4); - assert_eq!(n.len(), 1); - for elt in 1..5 { - assert_eq!(m.pop_front(), Some(elt)); - } - for elt in 5..6 { - assert_eq!(n.pop_front(), Some(elt)); - } - } - - // no-op on the last index - { - let mut m = LinkedList::new(); - m.push_back(1); - - let p = m.split_off(1); - assert_eq!(m.len(), 1); - assert_eq!(p.len(), 0); - assert_eq!(m.back(), Some(&1)); - assert_eq!(m.front(), Some(&1)); - } -} - -#[test] -fn test_iterator() { - let m = generate_test(); - for (i, elt) in m.iter().enumerate() { - assert_eq!(i as i32, *elt); - } - let mut n = LinkedList::new(); - assert_eq!(n.iter().next(), None); - n.push_front(4); - let mut it = n.iter(); - assert_eq!(it.size_hint(), (1, Some(1))); - assert_eq!(it.next().unwrap(), &4); - assert_eq!(it.size_hint(), (0, Some(0))); - assert_eq!(it.next(), None); -} - -#[test] -fn test_iterator_clone() { - let mut n = LinkedList::new(); - n.push_back(2); - n.push_back(3); - n.push_back(4); - let mut it = n.iter(); - it.next(); - let mut jt = it.clone(); - assert_eq!(it.next(), jt.next()); - assert_eq!(it.next_back(), jt.next_back()); - assert_eq!(it.next(), jt.next()); -} - -#[test] -fn test_iterator_double_end() { - let mut n = LinkedList::new(); - assert_eq!(n.iter().next(), None); - n.push_front(4); - n.push_front(5); - n.push_front(6); - let mut it = n.iter(); - assert_eq!(it.size_hint(), (3, Some(3))); - assert_eq!(it.next().unwrap(), &6); - assert_eq!(it.size_hint(), (2, Some(2))); - assert_eq!(it.next_back().unwrap(), &4); - assert_eq!(it.size_hint(), (1, Some(1))); - assert_eq!(it.next_back().unwrap(), &5); - assert_eq!(it.next_back(), None); - assert_eq!(it.next(), None); -} - -#[test] -fn test_rev_iter() { - let m = generate_test(); - for (i, elt) in m.iter().rev().enumerate() { - assert_eq!((6 - i) as i32, *elt); - } - let mut n = LinkedList::new(); - assert_eq!(n.iter().rev().next(), None); - n.push_front(4); - let mut it = n.iter().rev(); - assert_eq!(it.size_hint(), (1, Some(1))); - assert_eq!(it.next().unwrap(), &4); - assert_eq!(it.size_hint(), (0, Some(0))); - assert_eq!(it.next(), None); -} - -#[test] -fn test_mut_iter() { - let mut m = generate_test(); - let mut len = m.len(); - for (i, elt) in m.iter_mut().enumerate() { - assert_eq!(i as i32, *elt); - len -= 1; - } - assert_eq!(len, 0); - let mut n = LinkedList::new(); - assert!(n.iter_mut().next().is_none()); - n.push_front(4); - n.push_back(5); - let mut it = n.iter_mut(); - assert_eq!(it.size_hint(), (2, Some(2))); - assert!(it.next().is_some()); - assert!(it.next().is_some()); - assert_eq!(it.size_hint(), (0, Some(0))); - assert!(it.next().is_none()); -} - -#[test] -fn test_iterator_mut_double_end() { - let mut n = LinkedList::new(); - assert!(n.iter_mut().next_back().is_none()); - n.push_front(4); - n.push_front(5); - n.push_front(6); - let mut it = n.iter_mut(); - assert_eq!(it.size_hint(), (3, Some(3))); - assert_eq!(*it.next().unwrap(), 6); - assert_eq!(it.size_hint(), (2, Some(2))); - assert_eq!(*it.next_back().unwrap(), 4); - assert_eq!(it.size_hint(), (1, Some(1))); - assert_eq!(*it.next_back().unwrap(), 5); - assert!(it.next_back().is_none()); - assert!(it.next().is_none()); -} - -#[test] -fn test_mut_rev_iter() { - let mut m = generate_test(); - for (i, elt) in m.iter_mut().rev().enumerate() { - assert_eq!((6 - i) as i32, *elt); - } - let mut n = LinkedList::new(); - assert!(n.iter_mut().rev().next().is_none()); - n.push_front(4); - let mut it = n.iter_mut().rev(); - assert!(it.next().is_some()); - assert!(it.next().is_none()); -} - -#[test] -fn test_eq() { - let mut n = list_from(&[]); - let mut m = list_from(&[]); - assert!(n == m); - n.push_front(1); - assert!(n != m); - m.push_back(1); - assert!(n == m); - - let n = list_from(&[2, 3, 4]); - let m = list_from(&[1, 2, 3]); - assert!(n != m); -} - -#[test] -fn test_hash() { - use crate::hash; - - let mut x = LinkedList::new(); - let mut y = LinkedList::new(); - - assert!(hash(&x) == hash(&y)); - - x.push_back(1); - x.push_back(2); - x.push_back(3); - - y.push_front(3); - y.push_front(2); - y.push_front(1); - - assert!(hash(&x) == hash(&y)); -} - -#[test] -fn test_ord() { - let n = list_from(&[]); - let m = list_from(&[1, 2, 3]); - assert!(n < m); - assert!(m > n); - assert!(n <= n); - assert!(n >= n); -} - -#[test] -fn test_ord_nan() { - let nan = 0.0f64 / 0.0; - let n = list_from(&[nan]); - let m = list_from(&[nan]); - assert!(!(n < m)); - assert!(!(n > m)); - assert!(!(n <= m)); - assert!(!(n >= m)); - - let n = list_from(&[nan]); - let one = list_from(&[1.0f64]); - assert!(!(n < one)); - assert!(!(n > one)); - assert!(!(n <= one)); - assert!(!(n >= one)); - - let u = list_from(&[1.0f64, 2.0, nan]); - let v = list_from(&[1.0f64, 2.0, 3.0]); - assert!(!(u < v)); - assert!(!(u > v)); - assert!(!(u <= v)); - assert!(!(u >= v)); - - let s = list_from(&[1.0f64, 2.0, 4.0, 2.0]); - let t = list_from(&[1.0f64, 2.0, 3.0, 2.0]); - assert!(!(s < t)); - assert!(s > one); - assert!(!(s <= one)); - assert!(s >= one); -} - -#[test] -fn test_show() { - let list: LinkedList<_> = (0..10).collect(); - assert_eq!(format!("{:?}", list), "[0, 1, 2, 3, 4, 5, 6, 7, 8, 9]"); - - let list: LinkedList<_> = vec!["just", "one", "test", "more"].iter().cloned().collect(); - assert_eq!(format!("{:?}", list), "[\"just\", \"one\", \"test\", \"more\"]"); -} - -#[test] -fn test_extend_ref() { - let mut a = LinkedList::new(); - a.push_back(1); - - a.extend(&[2, 3, 4]); - - assert_eq!(a.len(), 4); - assert_eq!(a, list_from(&[1, 2, 3, 4])); - - let mut b = LinkedList::new(); - b.push_back(5); - b.push_back(6); - a.extend(&b); - - assert_eq!(a.len(), 6); - assert_eq!(a, list_from(&[1, 2, 3, 4, 5, 6])); -} - -#[test] -fn test_extend() { - let mut a = LinkedList::new(); - a.push_back(1); - a.extend(vec![2, 3, 4]); // uses iterator - - assert_eq!(a.len(), 4); - assert!(a.iter().eq(&[1, 2, 3, 4])); - - let b: LinkedList<_> = vec![5, 6, 7].into_iter().collect(); - a.extend(b); // specializes to `append` - - assert_eq!(a.len(), 7); - assert!(a.iter().eq(&[1, 2, 3, 4, 5, 6, 7])); -} - -#[test] -fn test_contains() { - let mut l = LinkedList::new(); - l.extend(&[2, 3, 4]); - - assert!(l.contains(&3)); - assert!(!l.contains(&1)); - - l.clear(); - - assert!(!l.contains(&3)); -} - -#[test] -fn drain_filter_empty() { - let mut list: LinkedList<i32> = LinkedList::new(); - - { - let mut iter = list.drain_filter(|_| true); - assert_eq!(iter.size_hint(), (0, Some(0))); - assert_eq!(iter.next(), None); - assert_eq!(iter.size_hint(), (0, Some(0))); - assert_eq!(iter.next(), None); - assert_eq!(iter.size_hint(), (0, Some(0))); - } - - assert_eq!(list.len(), 0); - assert_eq!(list.into_iter().collect::<Vec<_>>(), vec![]); -} - -#[test] -fn drain_filter_zst() { - let mut list: LinkedList<_> = vec![(), (), (), (), ()].into_iter().collect(); - let initial_len = list.len(); - let mut count = 0; - - { - let mut iter = list.drain_filter(|_| true); - assert_eq!(iter.size_hint(), (0, Some(initial_len))); - while let Some(_) = iter.next() { - count += 1; - assert_eq!(iter.size_hint(), (0, Some(initial_len - count))); - } - assert_eq!(iter.size_hint(), (0, Some(0))); - assert_eq!(iter.next(), None); - assert_eq!(iter.size_hint(), (0, Some(0))); - } - - assert_eq!(count, initial_len); - assert_eq!(list.len(), 0); - assert_eq!(list.into_iter().collect::<Vec<_>>(), vec![]); -} - -#[test] -fn drain_filter_false() { - let mut list: LinkedList<_> = vec![1, 2, 3, 4, 5, 6, 7, 8, 9, 10].into_iter().collect(); - - let initial_len = list.len(); - let mut count = 0; - - { - let mut iter = list.drain_filter(|_| false); - assert_eq!(iter.size_hint(), (0, Some(initial_len))); - for _ in iter.by_ref() { - count += 1; - } - assert_eq!(iter.size_hint(), (0, Some(0))); - assert_eq!(iter.next(), None); - assert_eq!(iter.size_hint(), (0, Some(0))); - } - - assert_eq!(count, 0); - assert_eq!(list.len(), initial_len); - assert_eq!(list.into_iter().collect::<Vec<_>>(), vec![1, 2, 3, 4, 5, 6, 7, 8, 9, 10]); -} - -#[test] -fn drain_filter_true() { - let mut list: LinkedList<_> = vec![1, 2, 3, 4, 5, 6, 7, 8, 9, 10].into_iter().collect(); - - let initial_len = list.len(); - let mut count = 0; - - { - let mut iter = list.drain_filter(|_| true); - assert_eq!(iter.size_hint(), (0, Some(initial_len))); - while let Some(_) = iter.next() { - count += 1; - assert_eq!(iter.size_hint(), (0, Some(initial_len - count))); - } - assert_eq!(iter.size_hint(), (0, Some(0))); - assert_eq!(iter.next(), None); - assert_eq!(iter.size_hint(), (0, Some(0))); - } - - assert_eq!(count, initial_len); - assert_eq!(list.len(), 0); - assert_eq!(list.into_iter().collect::<Vec<_>>(), vec![]); -} - -#[test] -fn drain_filter_complex() { - { - // [+xxx++++++xxxxx++++x+x++] - let mut list = vec![ - 1, 2, 4, 6, 7, 9, 11, 13, 15, 17, 18, 20, 22, 24, 26, 27, 29, 31, 33, 34, 35, 36, 37, - 39, - ] - .into_iter() - .collect::<LinkedList<_>>(); - - let removed = list.drain_filter(|x| *x % 2 == 0).collect::<Vec<_>>(); - assert_eq!(removed.len(), 10); - assert_eq!(removed, vec![2, 4, 6, 18, 20, 22, 24, 26, 34, 36]); - - assert_eq!(list.len(), 14); - assert_eq!( - list.into_iter().collect::<Vec<_>>(), - vec![1, 7, 9, 11, 13, 15, 17, 27, 29, 31, 33, 35, 37, 39] - ); - } - - { - // [xxx++++++xxxxx++++x+x++] - let mut list = vec![ - 2, 4, 6, 7, 9, 11, 13, 15, 17, 18, 20, 22, 24, 26, 27, 29, 31, 33, 34, 35, 36, 37, 39, - ] - .into_iter() - .collect::<LinkedList<_>>(); - - let removed = list.drain_filter(|x| *x % 2 == 0).collect::<Vec<_>>(); - assert_eq!(removed.len(), 10); - assert_eq!(removed, vec![2, 4, 6, 18, 20, 22, 24, 26, 34, 36]); - - assert_eq!(list.len(), 13); - assert_eq!( - list.into_iter().collect::<Vec<_>>(), - vec![7, 9, 11, 13, 15, 17, 27, 29, 31, 33, 35, 37, 39] - ); - } - - { - // [xxx++++++xxxxx++++x+x] - let mut list = - vec![2, 4, 6, 7, 9, 11, 13, 15, 17, 18, 20, 22, 24, 26, 27, 29, 31, 33, 34, 35, 36] - .into_iter() - .collect::<LinkedList<_>>(); - - let removed = list.drain_filter(|x| *x % 2 == 0).collect::<Vec<_>>(); - assert_eq!(removed.len(), 10); - assert_eq!(removed, vec![2, 4, 6, 18, 20, 22, 24, 26, 34, 36]); - - assert_eq!(list.len(), 11); - assert_eq!( - list.into_iter().collect::<Vec<_>>(), - vec![7, 9, 11, 13, 15, 17, 27, 29, 31, 33, 35] - ); - } - - { - // [xxxxxxxxxx+++++++++++] - let mut list = vec![2, 4, 6, 8, 10, 12, 14, 16, 18, 20, 1, 3, 5, 7, 9, 11, 13, 15, 17, 19] - .into_iter() - .collect::<LinkedList<_>>(); - - let removed = list.drain_filter(|x| *x % 2 == 0).collect::<Vec<_>>(); - assert_eq!(removed.len(), 10); - assert_eq!(removed, vec![2, 4, 6, 8, 10, 12, 14, 16, 18, 20]); - - assert_eq!(list.len(), 10); - assert_eq!(list.into_iter().collect::<Vec<_>>(), vec![1, 3, 5, 7, 9, 11, 13, 15, 17, 19]); - } - - { - // [+++++++++++xxxxxxxxxx] - let mut list = vec![1, 3, 5, 7, 9, 11, 13, 15, 17, 19, 2, 4, 6, 8, 10, 12, 14, 16, 18, 20] - .into_iter() - .collect::<LinkedList<_>>(); - - let removed = list.drain_filter(|x| *x % 2 == 0).collect::<Vec<_>>(); - assert_eq!(removed.len(), 10); - assert_eq!(removed, vec![2, 4, 6, 8, 10, 12, 14, 16, 18, 20]); - - assert_eq!(list.len(), 10); - assert_eq!(list.into_iter().collect::<Vec<_>>(), vec![1, 3, 5, 7, 9, 11, 13, 15, 17, 19]); - } -} - -#[test] -fn drain_filter_drop_panic_leak() { - static mut DROPS: i32 = 0; - - struct D(bool); - - impl Drop for D { - fn drop(&mut self) { - unsafe { - DROPS += 1; - } - - if self.0 { - panic!("panic in `drop`"); - } - } - } - - let mut q = LinkedList::new(); - q.push_back(D(false)); - q.push_back(D(false)); - q.push_back(D(false)); - q.push_back(D(false)); - q.push_back(D(false)); - q.push_front(D(false)); - q.push_front(D(true)); - q.push_front(D(false)); - - catch_unwind(AssertUnwindSafe(|| drop(q.drain_filter(|_| true)))).ok(); - - assert_eq!(unsafe { DROPS }, 8); - assert!(q.is_empty()); -} - -#[test] -fn drain_filter_pred_panic_leak() { - static mut DROPS: i32 = 0; - - #[derive(Debug)] - struct D(u32); - - impl Drop for D { - fn drop(&mut self) { - unsafe { - DROPS += 1; - } - } - } - - let mut q = LinkedList::new(); - q.push_back(D(3)); - q.push_back(D(4)); - q.push_back(D(5)); - q.push_back(D(6)); - q.push_back(D(7)); - q.push_front(D(2)); - q.push_front(D(1)); - q.push_front(D(0)); - - catch_unwind(AssertUnwindSafe(|| { - drop(q.drain_filter(|item| if item.0 >= 2 { panic!() } else { true })) - })) - .ok(); - - assert_eq!(unsafe { DROPS }, 2); // 0 and 1 - assert_eq!(q.len(), 6); -} - -#[test] -fn test_drop() { - static mut DROPS: i32 = 0; - struct Elem; - impl Drop for Elem { - fn drop(&mut self) { - unsafe { - DROPS += 1; - } - } - } - - let mut ring = LinkedList::new(); - ring.push_back(Elem); - ring.push_front(Elem); - ring.push_back(Elem); - ring.push_front(Elem); - drop(ring); - - assert_eq!(unsafe { DROPS }, 4); -} - -#[test] -fn test_drop_with_pop() { - static mut DROPS: i32 = 0; - struct Elem; - impl Drop for Elem { - fn drop(&mut self) { - unsafe { - DROPS += 1; - } - } - } - - let mut ring = LinkedList::new(); - ring.push_back(Elem); - ring.push_front(Elem); - ring.push_back(Elem); - ring.push_front(Elem); - - drop(ring.pop_back()); - drop(ring.pop_front()); - assert_eq!(unsafe { DROPS }, 2); - - drop(ring); - assert_eq!(unsafe { DROPS }, 4); -} - -#[test] -fn test_drop_clear() { - static mut DROPS: i32 = 0; - struct Elem; - impl Drop for Elem { - fn drop(&mut self) { - unsafe { - DROPS += 1; - } - } - } - - let mut ring = LinkedList::new(); - ring.push_back(Elem); - ring.push_front(Elem); - ring.push_back(Elem); - ring.push_front(Elem); - ring.clear(); - assert_eq!(unsafe { DROPS }, 4); - - drop(ring); - assert_eq!(unsafe { DROPS }, 4); -} - -#[test] -fn test_drop_panic() { - static mut DROPS: i32 = 0; - - struct D(bool); - - impl Drop for D { - fn drop(&mut self) { - unsafe { - DROPS += 1; - } - - if self.0 { - panic!("panic in `drop`"); - } - } - } - - let mut q = LinkedList::new(); - q.push_back(D(false)); - q.push_back(D(false)); - q.push_back(D(false)); - q.push_back(D(false)); - q.push_back(D(false)); - q.push_front(D(false)); - q.push_front(D(false)); - q.push_front(D(true)); - - catch_unwind(move || drop(q)).ok(); - - assert_eq!(unsafe { DROPS }, 8); -} diff --git a/src/liballoc/tests/rc.rs b/src/liballoc/tests/rc.rs deleted file mode 100644 index 501b4f0f816..00000000000 --- a/src/liballoc/tests/rc.rs +++ /dev/null @@ -1,193 +0,0 @@ -use std::any::Any; -use std::cell::RefCell; -use std::cmp::PartialEq; -use std::iter::TrustedLen; -use std::mem; -use std::rc::{Rc, Weak}; - -#[test] -fn uninhabited() { - enum Void {} - let mut a = Weak::<Void>::new(); - a = a.clone(); - assert!(a.upgrade().is_none()); - - let mut a: Weak<dyn Any> = a; // Unsizing - a = a.clone(); - assert!(a.upgrade().is_none()); -} - -#[test] -fn slice() { - let a: Rc<[u32; 3]> = Rc::new([3, 2, 1]); - let a: Rc<[u32]> = a; // Unsizing - let b: Rc<[u32]> = Rc::from(&[3, 2, 1][..]); // Conversion - assert_eq!(a, b); - - // Exercise is_dangling() with a DST - let mut a = Rc::downgrade(&a); - a = a.clone(); - assert!(a.upgrade().is_some()); -} - -#[test] -fn trait_object() { - let a: Rc<u32> = Rc::new(4); - let a: Rc<dyn Any> = a; // Unsizing - - // Exercise is_dangling() with a DST - let mut a = Rc::downgrade(&a); - a = a.clone(); - assert!(a.upgrade().is_some()); - - let mut b = Weak::<u32>::new(); - b = b.clone(); - assert!(b.upgrade().is_none()); - let mut b: Weak<dyn Any> = b; // Unsizing - b = b.clone(); - assert!(b.upgrade().is_none()); -} - -#[test] -fn float_nan_ne() { - let x = Rc::new(f32::NAN); - assert!(x != x); - assert!(!(x == x)); -} - -#[test] -fn partial_eq() { - struct TestPEq(RefCell<usize>); - impl PartialEq for TestPEq { - fn eq(&self, other: &TestPEq) -> bool { - *self.0.borrow_mut() += 1; - *other.0.borrow_mut() += 1; - true - } - } - let x = Rc::new(TestPEq(RefCell::new(0))); - assert!(x == x); - assert!(!(x != x)); - assert_eq!(*x.0.borrow(), 4); -} - -#[test] -fn eq() { - #[derive(Eq)] - struct TestEq(RefCell<usize>); - impl PartialEq for TestEq { - fn eq(&self, other: &TestEq) -> bool { - *self.0.borrow_mut() += 1; - *other.0.borrow_mut() += 1; - true - } - } - let x = Rc::new(TestEq(RefCell::new(0))); - assert!(x == x); - assert!(!(x != x)); - assert_eq!(*x.0.borrow(), 0); -} - -const SHARED_ITER_MAX: u16 = 100; - -fn assert_trusted_len<I: TrustedLen>(_: &I) {} - -#[test] -fn shared_from_iter_normal() { - // Exercise the base implementation for non-`TrustedLen` iterators. - { - // `Filter` is never `TrustedLen` since we don't - // know statically how many elements will be kept: - let iter = (0..SHARED_ITER_MAX).filter(|x| x % 2 == 0).map(Box::new); - - // Collecting into a `Vec<T>` or `Rc<[T]>` should make no difference: - let vec = iter.clone().collect::<Vec<_>>(); - let rc = iter.collect::<Rc<[_]>>(); - assert_eq!(&*vec, &*rc); - - // Clone a bit and let these get dropped. - { - let _rc_2 = rc.clone(); - let _rc_3 = rc.clone(); - let _rc_4 = Rc::downgrade(&_rc_3); - } - } // Drop what hasn't been here. -} - -#[test] -fn shared_from_iter_trustedlen_normal() { - // Exercise the `TrustedLen` implementation under normal circumstances - // where `size_hint()` matches `(_, Some(exact_len))`. - { - let iter = (0..SHARED_ITER_MAX).map(Box::new); - assert_trusted_len(&iter); - - // Collecting into a `Vec<T>` or `Rc<[T]>` should make no difference: - let vec = iter.clone().collect::<Vec<_>>(); - let rc = iter.collect::<Rc<[_]>>(); - assert_eq!(&*vec, &*rc); - assert_eq!(mem::size_of::<Box<u16>>() * SHARED_ITER_MAX as usize, mem::size_of_val(&*rc)); - - // Clone a bit and let these get dropped. - { - let _rc_2 = rc.clone(); - let _rc_3 = rc.clone(); - let _rc_4 = Rc::downgrade(&_rc_3); - } - } // Drop what hasn't been here. - - // Try a ZST to make sure it is handled well. - { - let iter = (0..SHARED_ITER_MAX).map(drop); - let vec = iter.clone().collect::<Vec<_>>(); - let rc = iter.collect::<Rc<[_]>>(); - assert_eq!(&*vec, &*rc); - assert_eq!(0, mem::size_of_val(&*rc)); - { - let _rc_2 = rc.clone(); - let _rc_3 = rc.clone(); - let _rc_4 = Rc::downgrade(&_rc_3); - } - } -} - -#[test] -#[should_panic = "I've almost got 99 problems."] -fn shared_from_iter_trustedlen_panic() { - // Exercise the `TrustedLen` implementation when `size_hint()` matches - // `(_, Some(exact_len))` but where `.next()` drops before the last iteration. - let iter = (0..SHARED_ITER_MAX).map(|val| match val { - 98 => panic!("I've almost got 99 problems."), - _ => Box::new(val), - }); - assert_trusted_len(&iter); - let _ = iter.collect::<Rc<[_]>>(); - - panic!("I am unreachable."); -} - -#[test] -fn shared_from_iter_trustedlen_no_fuse() { - // Exercise the `TrustedLen` implementation when `size_hint()` matches - // `(_, Some(exact_len))` but where the iterator does not behave in a fused manner. - struct Iter(std::vec::IntoIter<Option<Box<u8>>>); - - unsafe impl TrustedLen for Iter {} - - impl Iterator for Iter { - fn size_hint(&self) -> (usize, Option<usize>) { - (2, Some(2)) - } - - type Item = Box<u8>; - - fn next(&mut self) -> Option<Self::Item> { - self.0.next().flatten() - } - } - - let vec = vec![Some(Box::new(42)), Some(Box::new(24)), None, Some(Box::new(12))]; - let iter = Iter(vec.into_iter()); - assert_trusted_len(&iter); - assert_eq!(&[Box::new(42), Box::new(24)], &*iter.collect::<Rc<[_]>>()); -} diff --git a/src/liballoc/tests/slice.rs b/src/liballoc/tests/slice.rs deleted file mode 100644 index 75b76bb73ed..00000000000 --- a/src/liballoc/tests/slice.rs +++ /dev/null @@ -1,1771 +0,0 @@ -use std::cell::Cell; -use std::cmp::Ordering::{self, Equal, Greater, Less}; -use std::mem; -use std::panic; -use std::rc::Rc; -use std::sync::atomic::{AtomicUsize, Ordering::Relaxed}; - -use rand::distributions::Standard; -use rand::seq::SliceRandom; -use rand::{thread_rng, Rng, RngCore}; - -fn square(n: usize) -> usize { - n * n -} - -fn is_odd(n: &usize) -> bool { - *n % 2 == 1 -} - -#[test] -fn test_from_fn() { - // Test on-stack from_fn. - let mut v: Vec<_> = (0..3).map(square).collect(); - { - let v = v; - assert_eq!(v.len(), 3); - assert_eq!(v[0], 0); - assert_eq!(v[1], 1); - assert_eq!(v[2], 4); - } - - // Test on-heap from_fn. - v = (0..5).map(square).collect(); - { - let v = v; - assert_eq!(v.len(), 5); - assert_eq!(v[0], 0); - assert_eq!(v[1], 1); - assert_eq!(v[2], 4); - assert_eq!(v[3], 9); - assert_eq!(v[4], 16); - } -} - -#[test] -fn test_from_elem() { - // Test on-stack from_elem. - let mut v = vec![10, 10]; - { - let v = v; - assert_eq!(v.len(), 2); - assert_eq!(v[0], 10); - assert_eq!(v[1], 10); - } - - // Test on-heap from_elem. - v = vec![20; 6]; - { - let v = &v[..]; - assert_eq!(v[0], 20); - assert_eq!(v[1], 20); - assert_eq!(v[2], 20); - assert_eq!(v[3], 20); - assert_eq!(v[4], 20); - assert_eq!(v[5], 20); - } -} - -#[test] -fn test_is_empty() { - let xs: [i32; 0] = []; - assert!(xs.is_empty()); - assert!(![0].is_empty()); -} - -#[test] -fn test_len_divzero() { - type Z = [i8; 0]; - let v0: &[Z] = &[]; - let v1: &[Z] = &[[]]; - let v2: &[Z] = &[[], []]; - assert_eq!(mem::size_of::<Z>(), 0); - assert_eq!(v0.len(), 0); - assert_eq!(v1.len(), 1); - assert_eq!(v2.len(), 2); -} - -#[test] -fn test_get() { - let mut a = vec![11]; - assert_eq!(a.get(1), None); - a = vec![11, 12]; - assert_eq!(a.get(1).unwrap(), &12); - a = vec![11, 12, 13]; - assert_eq!(a.get(1).unwrap(), &12); -} - -#[test] -fn test_first() { - let mut a = vec![]; - assert_eq!(a.first(), None); - a = vec![11]; - assert_eq!(a.first().unwrap(), &11); - a = vec![11, 12]; - assert_eq!(a.first().unwrap(), &11); -} - -#[test] -fn test_first_mut() { - let mut a = vec![]; - assert_eq!(a.first_mut(), None); - a = vec![11]; - assert_eq!(*a.first_mut().unwrap(), 11); - a = vec![11, 12]; - assert_eq!(*a.first_mut().unwrap(), 11); -} - -#[test] -fn test_split_first() { - let mut a = vec![11]; - let b: &[i32] = &[]; - assert!(b.split_first().is_none()); - assert_eq!(a.split_first(), Some((&11, b))); - a = vec![11, 12]; - let b: &[i32] = &[12]; - assert_eq!(a.split_first(), Some((&11, b))); -} - -#[test] -fn test_split_first_mut() { - let mut a = vec![11]; - let b: &mut [i32] = &mut []; - assert!(b.split_first_mut().is_none()); - assert!(a.split_first_mut() == Some((&mut 11, b))); - a = vec![11, 12]; - let b: &mut [_] = &mut [12]; - assert!(a.split_first_mut() == Some((&mut 11, b))); -} - -#[test] -fn test_split_last() { - let mut a = vec![11]; - let b: &[i32] = &[]; - assert!(b.split_last().is_none()); - assert_eq!(a.split_last(), Some((&11, b))); - a = vec![11, 12]; - let b: &[_] = &[11]; - assert_eq!(a.split_last(), Some((&12, b))); -} - -#[test] -fn test_split_last_mut() { - let mut a = vec![11]; - let b: &mut [i32] = &mut []; - assert!(b.split_last_mut().is_none()); - assert!(a.split_last_mut() == Some((&mut 11, b))); - - a = vec![11, 12]; - let b: &mut [_] = &mut [11]; - assert!(a.split_last_mut() == Some((&mut 12, b))); -} - -#[test] -fn test_last() { - let mut a = vec![]; - assert_eq!(a.last(), None); - a = vec![11]; - assert_eq!(a.last().unwrap(), &11); - a = vec![11, 12]; - assert_eq!(a.last().unwrap(), &12); -} - -#[test] -fn test_last_mut() { - let mut a = vec![]; - assert_eq!(a.last_mut(), None); - a = vec![11]; - assert_eq!(*a.last_mut().unwrap(), 11); - a = vec![11, 12]; - assert_eq!(*a.last_mut().unwrap(), 12); -} - -#[test] -fn test_slice() { - // Test fixed length vector. - let vec_fixed = [1, 2, 3, 4]; - let v_a = vec_fixed[1..vec_fixed.len()].to_vec(); - assert_eq!(v_a.len(), 3); - - assert_eq!(v_a[0], 2); - assert_eq!(v_a[1], 3); - assert_eq!(v_a[2], 4); - - // Test on stack. - let vec_stack: &[_] = &[1, 2, 3]; - let v_b = vec_stack[1..3].to_vec(); - assert_eq!(v_b.len(), 2); - - assert_eq!(v_b[0], 2); - assert_eq!(v_b[1], 3); - - // Test `Box<[T]>` - let vec_unique = vec![1, 2, 3, 4, 5, 6]; - let v_d = vec_unique[1..6].to_vec(); - assert_eq!(v_d.len(), 5); - - assert_eq!(v_d[0], 2); - assert_eq!(v_d[1], 3); - assert_eq!(v_d[2], 4); - assert_eq!(v_d[3], 5); - assert_eq!(v_d[4], 6); -} - -#[test] -fn test_slice_from() { - let vec: &[_] = &[1, 2, 3, 4]; - assert_eq!(&vec[..], vec); - let b: &[_] = &[3, 4]; - assert_eq!(&vec[2..], b); - let b: &[_] = &[]; - assert_eq!(&vec[4..], b); -} - -#[test] -fn test_slice_to() { - let vec: &[_] = &[1, 2, 3, 4]; - assert_eq!(&vec[..4], vec); - let b: &[_] = &[1, 2]; - assert_eq!(&vec[..2], b); - let b: &[_] = &[]; - assert_eq!(&vec[..0], b); -} - -#[test] -fn test_pop() { - let mut v = vec![5]; - let e = v.pop(); - assert_eq!(v.len(), 0); - assert_eq!(e, Some(5)); - let f = v.pop(); - assert_eq!(f, None); - let g = v.pop(); - assert_eq!(g, None); -} - -#[test] -fn test_swap_remove() { - let mut v = vec![1, 2, 3, 4, 5]; - let mut e = v.swap_remove(0); - assert_eq!(e, 1); - assert_eq!(v, [5, 2, 3, 4]); - e = v.swap_remove(3); - assert_eq!(e, 4); - assert_eq!(v, [5, 2, 3]); -} - -#[test] -#[should_panic] -fn test_swap_remove_fail() { - let mut v = vec![1]; - let _ = v.swap_remove(0); - let _ = v.swap_remove(0); -} - -#[test] -fn test_swap_remove_noncopyable() { - // Tests that we don't accidentally run destructors twice. - let mut v: Vec<Box<_>> = Vec::new(); - v.push(box 0); - v.push(box 0); - v.push(box 0); - let mut _e = v.swap_remove(0); - assert_eq!(v.len(), 2); - _e = v.swap_remove(1); - assert_eq!(v.len(), 1); - _e = v.swap_remove(0); - assert_eq!(v.len(), 0); -} - -#[test] -fn test_push() { - // Test on-stack push(). - let mut v = vec![]; - v.push(1); - assert_eq!(v.len(), 1); - assert_eq!(v[0], 1); - - // Test on-heap push(). - v.push(2); - assert_eq!(v.len(), 2); - assert_eq!(v[0], 1); - assert_eq!(v[1], 2); -} - -#[test] -fn test_truncate() { - let mut v: Vec<Box<_>> = vec![box 6, box 5, box 4]; - v.truncate(1); - let v = v; - assert_eq!(v.len(), 1); - assert_eq!(*(v[0]), 6); - // If the unsafe block didn't drop things properly, we blow up here. -} - -#[test] -fn test_clear() { - let mut v: Vec<Box<_>> = vec![box 6, box 5, box 4]; - v.clear(); - assert_eq!(v.len(), 0); - // If the unsafe block didn't drop things properly, we blow up here. -} - -#[test] -fn test_retain() { - let mut v = vec![1, 2, 3, 4, 5]; - v.retain(is_odd); - assert_eq!(v, [1, 3, 5]); -} - -#[test] -fn test_binary_search() { - assert_eq!([1, 2, 3, 4, 5].binary_search(&5).ok(), Some(4)); - assert_eq!([1, 2, 3, 4, 5].binary_search(&4).ok(), Some(3)); - assert_eq!([1, 2, 3, 4, 5].binary_search(&3).ok(), Some(2)); - assert_eq!([1, 2, 3, 4, 5].binary_search(&2).ok(), Some(1)); - assert_eq!([1, 2, 3, 4, 5].binary_search(&1).ok(), Some(0)); - - assert_eq!([2, 4, 6, 8, 10].binary_search(&1).ok(), None); - assert_eq!([2, 4, 6, 8, 10].binary_search(&5).ok(), None); - assert_eq!([2, 4, 6, 8, 10].binary_search(&4).ok(), Some(1)); - assert_eq!([2, 4, 6, 8, 10].binary_search(&10).ok(), Some(4)); - - assert_eq!([2, 4, 6, 8].binary_search(&1).ok(), None); - assert_eq!([2, 4, 6, 8].binary_search(&5).ok(), None); - assert_eq!([2, 4, 6, 8].binary_search(&4).ok(), Some(1)); - assert_eq!([2, 4, 6, 8].binary_search(&8).ok(), Some(3)); - - assert_eq!([2, 4, 6].binary_search(&1).ok(), None); - assert_eq!([2, 4, 6].binary_search(&5).ok(), None); - assert_eq!([2, 4, 6].binary_search(&4).ok(), Some(1)); - assert_eq!([2, 4, 6].binary_search(&6).ok(), Some(2)); - - assert_eq!([2, 4].binary_search(&1).ok(), None); - assert_eq!([2, 4].binary_search(&5).ok(), None); - assert_eq!([2, 4].binary_search(&2).ok(), Some(0)); - assert_eq!([2, 4].binary_search(&4).ok(), Some(1)); - - assert_eq!([2].binary_search(&1).ok(), None); - assert_eq!([2].binary_search(&5).ok(), None); - assert_eq!([2].binary_search(&2).ok(), Some(0)); - - assert_eq!([].binary_search(&1).ok(), None); - assert_eq!([].binary_search(&5).ok(), None); - - assert!([1, 1, 1, 1, 1].binary_search(&1).ok() != None); - assert!([1, 1, 1, 1, 2].binary_search(&1).ok() != None); - assert!([1, 1, 1, 2, 2].binary_search(&1).ok() != None); - assert!([1, 1, 2, 2, 2].binary_search(&1).ok() != None); - assert_eq!([1, 2, 2, 2, 2].binary_search(&1).ok(), Some(0)); - - assert_eq!([1, 2, 3, 4, 5].binary_search(&6).ok(), None); - assert_eq!([1, 2, 3, 4, 5].binary_search(&0).ok(), None); -} - -#[test] -fn test_reverse() { - let mut v = vec![10, 20]; - assert_eq!(v[0], 10); - assert_eq!(v[1], 20); - v.reverse(); - assert_eq!(v[0], 20); - assert_eq!(v[1], 10); - - let mut v3 = Vec::<i32>::new(); - v3.reverse(); - assert!(v3.is_empty()); - - // check the 1-byte-types path - let mut v = (-50..51i8).collect::<Vec<_>>(); - v.reverse(); - assert_eq!(v, (-50..51i8).rev().collect::<Vec<_>>()); - - // check the 2-byte-types path - let mut v = (-50..51i16).collect::<Vec<_>>(); - v.reverse(); - assert_eq!(v, (-50..51i16).rev().collect::<Vec<_>>()); -} - -#[test] -#[cfg_attr(miri, ignore)] // Miri is too slow -fn test_sort() { - let mut rng = thread_rng(); - - for len in (2..25).chain(500..510) { - for &modulus in &[5, 10, 100, 1000] { - for _ in 0..10 { - let orig: Vec<_> = - rng.sample_iter::<i32, _>(&Standard).map(|x| x % modulus).take(len).collect(); - - // Sort in default order. - let mut v = orig.clone(); - v.sort(); - assert!(v.windows(2).all(|w| w[0] <= w[1])); - - // Sort in ascending order. - let mut v = orig.clone(); - v.sort_by(|a, b| a.cmp(b)); - assert!(v.windows(2).all(|w| w[0] <= w[1])); - - // Sort in descending order. - let mut v = orig.clone(); - v.sort_by(|a, b| b.cmp(a)); - assert!(v.windows(2).all(|w| w[0] >= w[1])); - - // Sort in lexicographic order. - let mut v1 = orig.clone(); - let mut v2 = orig.clone(); - v1.sort_by_key(|x| x.to_string()); - v2.sort_by_cached_key(|x| x.to_string()); - assert!(v1.windows(2).all(|w| w[0].to_string() <= w[1].to_string())); - assert!(v1 == v2); - - // Sort with many pre-sorted runs. - let mut v = orig.clone(); - v.sort(); - v.reverse(); - for _ in 0..5 { - let a = rng.gen::<usize>() % len; - let b = rng.gen::<usize>() % len; - if a < b { - v[a..b].reverse(); - } else { - v.swap(a, b); - } - } - v.sort(); - assert!(v.windows(2).all(|w| w[0] <= w[1])); - } - } - } - - // Sort using a completely random comparison function. - // This will reorder the elements *somehow*, but won't panic. - let mut v = [0; 500]; - for i in 0..v.len() { - v[i] = i as i32; - } - v.sort_by(|_, _| *[Less, Equal, Greater].choose(&mut rng).unwrap()); - v.sort(); - for i in 0..v.len() { - assert_eq!(v[i], i as i32); - } - - // Should not panic. - [0i32; 0].sort(); - [(); 10].sort(); - [(); 100].sort(); - - let mut v = [0xDEADBEEFu64]; - v.sort(); - assert!(v == [0xDEADBEEF]); -} - -#[test] -fn test_sort_stability() { - // Miri is too slow - let large_range = if cfg!(miri) { 0..0 } else { 500..510 }; - let rounds = if cfg!(miri) { 1 } else { 10 }; - - for len in (2..25).chain(large_range) { - for _ in 0..rounds { - let mut counts = [0; 10]; - - // create a vector like [(6, 1), (5, 1), (6, 2), ...], - // where the first item of each tuple is random, but - // the second item represents which occurrence of that - // number this element is, i.e., the second elements - // will occur in sorted order. - let orig: Vec<_> = (0..len) - .map(|_| { - let n = thread_rng().gen::<usize>() % 10; - counts[n] += 1; - (n, counts[n]) - }) - .collect(); - - let mut v = orig.clone(); - // Only sort on the first element, so an unstable sort - // may mix up the counts. - v.sort_by(|&(a, _), &(b, _)| a.cmp(&b)); - - // This comparison includes the count (the second item - // of the tuple), so elements with equal first items - // will need to be ordered with increasing - // counts... i.e., exactly asserting that this sort is - // stable. - assert!(v.windows(2).all(|w| w[0] <= w[1])); - - let mut v = orig.clone(); - v.sort_by_cached_key(|&(x, _)| x); - assert!(v.windows(2).all(|w| w[0] <= w[1])); - } - } -} - -#[test] -fn test_rotate_left() { - let expected: Vec<_> = (0..13).collect(); - let mut v = Vec::new(); - - // no-ops - v.clone_from(&expected); - v.rotate_left(0); - assert_eq!(v, expected); - v.rotate_left(expected.len()); - assert_eq!(v, expected); - let mut zst_array = [(), (), ()]; - zst_array.rotate_left(2); - - // happy path - v = (5..13).chain(0..5).collect(); - v.rotate_left(8); - assert_eq!(v, expected); - - let expected: Vec<_> = (0..1000).collect(); - - // small rotations in large slice, uses ptr::copy - v = (2..1000).chain(0..2).collect(); - v.rotate_left(998); - assert_eq!(v, expected); - v = (998..1000).chain(0..998).collect(); - v.rotate_left(2); - assert_eq!(v, expected); - - // non-small prime rotation, has a few rounds of swapping - v = (389..1000).chain(0..389).collect(); - v.rotate_left(1000 - 389); - assert_eq!(v, expected); -} - -#[test] -fn test_rotate_right() { - let expected: Vec<_> = (0..13).collect(); - let mut v = Vec::new(); - - // no-ops - v.clone_from(&expected); - v.rotate_right(0); - assert_eq!(v, expected); - v.rotate_right(expected.len()); - assert_eq!(v, expected); - let mut zst_array = [(), (), ()]; - zst_array.rotate_right(2); - - // happy path - v = (5..13).chain(0..5).collect(); - v.rotate_right(5); - assert_eq!(v, expected); - - let expected: Vec<_> = (0..1000).collect(); - - // small rotations in large slice, uses ptr::copy - v = (2..1000).chain(0..2).collect(); - v.rotate_right(2); - assert_eq!(v, expected); - v = (998..1000).chain(0..998).collect(); - v.rotate_right(998); - assert_eq!(v, expected); - - // non-small prime rotation, has a few rounds of swapping - v = (389..1000).chain(0..389).collect(); - v.rotate_right(389); - assert_eq!(v, expected); -} - -#[test] -fn test_concat() { - let v: [Vec<i32>; 0] = []; - let c = v.concat(); - assert_eq!(c, []); - let d = [vec![1], vec![2, 3]].concat(); - assert_eq!(d, [1, 2, 3]); - - let v: &[&[_]] = &[&[1], &[2, 3]]; - assert_eq!(v.join(&0), [1, 0, 2, 3]); - let v: &[&[_]] = &[&[1], &[2], &[3]]; - assert_eq!(v.join(&0), [1, 0, 2, 0, 3]); -} - -#[test] -fn test_join() { - let v: [Vec<i32>; 0] = []; - assert_eq!(v.join(&0), []); - assert_eq!([vec![1], vec![2, 3]].join(&0), [1, 0, 2, 3]); - assert_eq!([vec![1], vec![2], vec![3]].join(&0), [1, 0, 2, 0, 3]); - - let v: [&[_]; 2] = [&[1], &[2, 3]]; - assert_eq!(v.join(&0), [1, 0, 2, 3]); - let v: [&[_]; 3] = [&[1], &[2], &[3]]; - assert_eq!(v.join(&0), [1, 0, 2, 0, 3]); -} - -#[test] -fn test_join_nocopy() { - let v: [String; 0] = []; - assert_eq!(v.join(","), ""); - assert_eq!(["a".to_string(), "ab".into()].join(","), "a,ab"); - assert_eq!(["a".to_string(), "ab".into(), "abc".into()].join(","), "a,ab,abc"); - assert_eq!(["a".to_string(), "ab".into(), "".into()].join(","), "a,ab,"); -} - -#[test] -fn test_insert() { - let mut a = vec![1, 2, 4]; - a.insert(2, 3); - assert_eq!(a, [1, 2, 3, 4]); - - let mut a = vec![1, 2, 3]; - a.insert(0, 0); - assert_eq!(a, [0, 1, 2, 3]); - - let mut a = vec![1, 2, 3]; - a.insert(3, 4); - assert_eq!(a, [1, 2, 3, 4]); - - let mut a = vec![]; - a.insert(0, 1); - assert_eq!(a, [1]); -} - -#[test] -#[should_panic] -fn test_insert_oob() { - let mut a = vec![1, 2, 3]; - a.insert(4, 5); -} - -#[test] -fn test_remove() { - let mut a = vec![1, 2, 3, 4]; - - assert_eq!(a.remove(2), 3); - assert_eq!(a, [1, 2, 4]); - - assert_eq!(a.remove(2), 4); - assert_eq!(a, [1, 2]); - - assert_eq!(a.remove(0), 1); - assert_eq!(a, [2]); - - assert_eq!(a.remove(0), 2); - assert_eq!(a, []); -} - -#[test] -#[should_panic] -fn test_remove_fail() { - let mut a = vec![1]; - let _ = a.remove(0); - let _ = a.remove(0); -} - -#[test] -fn test_capacity() { - let mut v = vec![0]; - v.reserve_exact(10); - assert!(v.capacity() >= 11); -} - -#[test] -fn test_slice_2() { - let v = vec![1, 2, 3, 4, 5]; - let v = &v[1..3]; - assert_eq!(v.len(), 2); - assert_eq!(v[0], 2); - assert_eq!(v[1], 3); -} - -macro_rules! assert_order { - (Greater, $a:expr, $b:expr) => { - assert_eq!($a.cmp($b), Greater); - assert!($a > $b); - }; - (Less, $a:expr, $b:expr) => { - assert_eq!($a.cmp($b), Less); - assert!($a < $b); - }; - (Equal, $a:expr, $b:expr) => { - assert_eq!($a.cmp($b), Equal); - assert_eq!($a, $b); - }; -} - -#[test] -fn test_total_ord_u8() { - let c = &[1u8, 2, 3]; - assert_order!(Greater, &[1u8, 2, 3, 4][..], &c[..]); - let c = &[1u8, 2, 3, 4]; - assert_order!(Less, &[1u8, 2, 3][..], &c[..]); - let c = &[1u8, 2, 3, 6]; - assert_order!(Equal, &[1u8, 2, 3, 6][..], &c[..]); - let c = &[1u8, 2, 3, 4, 5, 6]; - assert_order!(Less, &[1u8, 2, 3, 4, 5, 5, 5, 5][..], &c[..]); - let c = &[1u8, 2, 3, 4]; - assert_order!(Greater, &[2u8, 2][..], &c[..]); -} - -#[test] -fn test_total_ord_i32() { - let c = &[1, 2, 3]; - assert_order!(Greater, &[1, 2, 3, 4][..], &c[..]); - let c = &[1, 2, 3, 4]; - assert_order!(Less, &[1, 2, 3][..], &c[..]); - let c = &[1, 2, 3, 6]; - assert_order!(Equal, &[1, 2, 3, 6][..], &c[..]); - let c = &[1, 2, 3, 4, 5, 6]; - assert_order!(Less, &[1, 2, 3, 4, 5, 5, 5, 5][..], &c[..]); - let c = &[1, 2, 3, 4]; - assert_order!(Greater, &[2, 2][..], &c[..]); -} - -#[test] -fn test_iterator() { - let xs = [1, 2, 5, 10, 11]; - let mut it = xs.iter(); - assert_eq!(it.size_hint(), (5, Some(5))); - assert_eq!(it.next().unwrap(), &1); - assert_eq!(it.size_hint(), (4, Some(4))); - assert_eq!(it.next().unwrap(), &2); - assert_eq!(it.size_hint(), (3, Some(3))); - assert_eq!(it.next().unwrap(), &5); - assert_eq!(it.size_hint(), (2, Some(2))); - assert_eq!(it.next().unwrap(), &10); - assert_eq!(it.size_hint(), (1, Some(1))); - assert_eq!(it.next().unwrap(), &11); - assert_eq!(it.size_hint(), (0, Some(0))); - assert!(it.next().is_none()); -} - -#[test] -fn test_iter_size_hints() { - let mut xs = [1, 2, 5, 10, 11]; - assert_eq!(xs.iter().size_hint(), (5, Some(5))); - assert_eq!(xs.iter_mut().size_hint(), (5, Some(5))); -} - -#[test] -fn test_iter_as_slice() { - let xs = [1, 2, 5, 10, 11]; - let mut iter = xs.iter(); - assert_eq!(iter.as_slice(), &[1, 2, 5, 10, 11]); - iter.next(); - assert_eq!(iter.as_slice(), &[2, 5, 10, 11]); -} - -#[test] -fn test_iter_as_ref() { - let xs = [1, 2, 5, 10, 11]; - let mut iter = xs.iter(); - assert_eq!(iter.as_ref(), &[1, 2, 5, 10, 11]); - iter.next(); - assert_eq!(iter.as_ref(), &[2, 5, 10, 11]); -} - -#[test] -fn test_iter_clone() { - let xs = [1, 2, 5]; - let mut it = xs.iter(); - it.next(); - let mut jt = it.clone(); - assert_eq!(it.next(), jt.next()); - assert_eq!(it.next(), jt.next()); - assert_eq!(it.next(), jt.next()); -} - -#[test] -fn test_iter_is_empty() { - let xs = [1, 2, 5, 10, 11]; - for i in 0..xs.len() { - for j in i..xs.len() { - assert_eq!(xs[i..j].iter().is_empty(), xs[i..j].is_empty()); - } - } -} - -#[test] -fn test_mut_iterator() { - let mut xs = [1, 2, 3, 4, 5]; - for x in &mut xs { - *x += 1; - } - assert!(xs == [2, 3, 4, 5, 6]) -} - -#[test] -fn test_rev_iterator() { - let xs = [1, 2, 5, 10, 11]; - let ys = [11, 10, 5, 2, 1]; - let mut i = 0; - for &x in xs.iter().rev() { - assert_eq!(x, ys[i]); - i += 1; - } - assert_eq!(i, 5); -} - -#[test] -fn test_mut_rev_iterator() { - let mut xs = [1, 2, 3, 4, 5]; - for (i, x) in xs.iter_mut().rev().enumerate() { - *x += i; - } - assert!(xs == [5, 5, 5, 5, 5]) -} - -#[test] -fn test_move_iterator() { - let xs = vec![1, 2, 3, 4, 5]; - assert_eq!(xs.into_iter().fold(0, |a: usize, b: usize| 10 * a + b), 12345); -} - -#[test] -fn test_move_rev_iterator() { - let xs = vec![1, 2, 3, 4, 5]; - assert_eq!(xs.into_iter().rev().fold(0, |a: usize, b: usize| 10 * a + b), 54321); -} - -#[test] -fn test_splitator() { - let xs = &[1, 2, 3, 4, 5]; - - let splits: &[&[_]] = &[&[1], &[3], &[5]]; - assert_eq!(xs.split(|x| *x % 2 == 0).collect::<Vec<_>>(), splits); - let splits: &[&[_]] = &[&[], &[2, 3, 4, 5]]; - assert_eq!(xs.split(|x| *x == 1).collect::<Vec<_>>(), splits); - let splits: &[&[_]] = &[&[1, 2, 3, 4], &[]]; - assert_eq!(xs.split(|x| *x == 5).collect::<Vec<_>>(), splits); - let splits: &[&[_]] = &[&[1, 2, 3, 4, 5]]; - assert_eq!(xs.split(|x| *x == 10).collect::<Vec<_>>(), splits); - let splits: &[&[_]] = &[&[], &[], &[], &[], &[], &[]]; - assert_eq!(xs.split(|_| true).collect::<Vec<&[i32]>>(), splits); - - let xs: &[i32] = &[]; - let splits: &[&[i32]] = &[&[]]; - assert_eq!(xs.split(|x| *x == 5).collect::<Vec<&[i32]>>(), splits); -} - -#[test] -fn test_splitator_inclusive() { - let xs = &[1, 2, 3, 4, 5]; - - let splits: &[&[_]] = &[&[1, 2], &[3, 4], &[5]]; - assert_eq!(xs.split_inclusive(|x| *x % 2 == 0).collect::<Vec<_>>(), splits); - let splits: &[&[_]] = &[&[1], &[2, 3, 4, 5]]; - assert_eq!(xs.split_inclusive(|x| *x == 1).collect::<Vec<_>>(), splits); - let splits: &[&[_]] = &[&[1, 2, 3, 4, 5]]; - assert_eq!(xs.split_inclusive(|x| *x == 5).collect::<Vec<_>>(), splits); - let splits: &[&[_]] = &[&[1, 2, 3, 4, 5]]; - assert_eq!(xs.split_inclusive(|x| *x == 10).collect::<Vec<_>>(), splits); - let splits: &[&[_]] = &[&[1], &[2], &[3], &[4], &[5]]; - assert_eq!(xs.split_inclusive(|_| true).collect::<Vec<&[i32]>>(), splits); - - let xs: &[i32] = &[]; - let splits: &[&[i32]] = &[&[]]; - assert_eq!(xs.split_inclusive(|x| *x == 5).collect::<Vec<&[i32]>>(), splits); -} - -#[test] -fn test_splitator_inclusive_reverse() { - let xs = &[1, 2, 3, 4, 5]; - - let splits: &[&[_]] = &[&[5], &[3, 4], &[1, 2]]; - assert_eq!(xs.split_inclusive(|x| *x % 2 == 0).rev().collect::<Vec<_>>(), splits); - let splits: &[&[_]] = &[&[2, 3, 4, 5], &[1]]; - assert_eq!(xs.split_inclusive(|x| *x == 1).rev().collect::<Vec<_>>(), splits); - let splits: &[&[_]] = &[&[1, 2, 3, 4, 5]]; - assert_eq!(xs.split_inclusive(|x| *x == 5).rev().collect::<Vec<_>>(), splits); - let splits: &[&[_]] = &[&[1, 2, 3, 4, 5]]; - assert_eq!(xs.split_inclusive(|x| *x == 10).rev().collect::<Vec<_>>(), splits); - let splits: &[&[_]] = &[&[5], &[4], &[3], &[2], &[1]]; - assert_eq!(xs.split_inclusive(|_| true).rev().collect::<Vec<_>>(), splits); - - let xs: &[i32] = &[]; - let splits: &[&[i32]] = &[&[]]; - assert_eq!(xs.split_inclusive(|x| *x == 5).rev().collect::<Vec<_>>(), splits); -} - -#[test] -fn test_splitator_mut_inclusive() { - let xs = &mut [1, 2, 3, 4, 5]; - - let splits: &[&[_]] = &[&[1, 2], &[3, 4], &[5]]; - assert_eq!(xs.split_inclusive_mut(|x| *x % 2 == 0).collect::<Vec<_>>(), splits); - let splits: &[&[_]] = &[&[1], &[2, 3, 4, 5]]; - assert_eq!(xs.split_inclusive_mut(|x| *x == 1).collect::<Vec<_>>(), splits); - let splits: &[&[_]] = &[&[1, 2, 3, 4, 5]]; - assert_eq!(xs.split_inclusive_mut(|x| *x == 5).collect::<Vec<_>>(), splits); - let splits: &[&[_]] = &[&[1, 2, 3, 4, 5]]; - assert_eq!(xs.split_inclusive_mut(|x| *x == 10).collect::<Vec<_>>(), splits); - let splits: &[&[_]] = &[&[1], &[2], &[3], &[4], &[5]]; - assert_eq!(xs.split_inclusive_mut(|_| true).collect::<Vec<_>>(), splits); - - let xs: &mut [i32] = &mut []; - let splits: &[&[i32]] = &[&[]]; - assert_eq!(xs.split_inclusive_mut(|x| *x == 5).collect::<Vec<_>>(), splits); -} - -#[test] -fn test_splitator_mut_inclusive_reverse() { - let xs = &mut [1, 2, 3, 4, 5]; - - let splits: &[&[_]] = &[&[5], &[3, 4], &[1, 2]]; - assert_eq!(xs.split_inclusive_mut(|x| *x % 2 == 0).rev().collect::<Vec<_>>(), splits); - let splits: &[&[_]] = &[&[2, 3, 4, 5], &[1]]; - assert_eq!(xs.split_inclusive_mut(|x| *x == 1).rev().collect::<Vec<_>>(), splits); - let splits: &[&[_]] = &[&[1, 2, 3, 4, 5]]; - assert_eq!(xs.split_inclusive_mut(|x| *x == 5).rev().collect::<Vec<_>>(), splits); - let splits: &[&[_]] = &[&[1, 2, 3, 4, 5]]; - assert_eq!(xs.split_inclusive_mut(|x| *x == 10).rev().collect::<Vec<_>>(), splits); - let splits: &[&[_]] = &[&[5], &[4], &[3], &[2], &[1]]; - assert_eq!(xs.split_inclusive_mut(|_| true).rev().collect::<Vec<_>>(), splits); - - let xs: &mut [i32] = &mut []; - let splits: &[&[i32]] = &[&[]]; - assert_eq!(xs.split_inclusive_mut(|x| *x == 5).rev().collect::<Vec<_>>(), splits); -} - -#[test] -fn test_splitnator() { - let xs = &[1, 2, 3, 4, 5]; - - let splits: &[&[_]] = &[&[1, 2, 3, 4, 5]]; - assert_eq!(xs.splitn(1, |x| *x % 2 == 0).collect::<Vec<_>>(), splits); - let splits: &[&[_]] = &[&[1], &[3, 4, 5]]; - assert_eq!(xs.splitn(2, |x| *x % 2 == 0).collect::<Vec<_>>(), splits); - let splits: &[&[_]] = &[&[], &[], &[], &[4, 5]]; - assert_eq!(xs.splitn(4, |_| true).collect::<Vec<_>>(), splits); - - let xs: &[i32] = &[]; - let splits: &[&[i32]] = &[&[]]; - assert_eq!(xs.splitn(2, |x| *x == 5).collect::<Vec<_>>(), splits); -} - -#[test] -fn test_splitnator_mut() { - let xs = &mut [1, 2, 3, 4, 5]; - - let splits: &[&mut [_]] = &[&mut [1, 2, 3, 4, 5]]; - assert_eq!(xs.splitn_mut(1, |x| *x % 2 == 0).collect::<Vec<_>>(), splits); - let splits: &[&mut [_]] = &[&mut [1], &mut [3, 4, 5]]; - assert_eq!(xs.splitn_mut(2, |x| *x % 2 == 0).collect::<Vec<_>>(), splits); - let splits: &[&mut [_]] = &[&mut [], &mut [], &mut [], &mut [4, 5]]; - assert_eq!(xs.splitn_mut(4, |_| true).collect::<Vec<_>>(), splits); - - let xs: &mut [i32] = &mut []; - let splits: &[&mut [i32]] = &[&mut []]; - assert_eq!(xs.splitn_mut(2, |x| *x == 5).collect::<Vec<_>>(), splits); -} - -#[test] -fn test_rsplitator() { - let xs = &[1, 2, 3, 4, 5]; - - let splits: &[&[_]] = &[&[5], &[3], &[1]]; - assert_eq!(xs.split(|x| *x % 2 == 0).rev().collect::<Vec<_>>(), splits); - let splits: &[&[_]] = &[&[2, 3, 4, 5], &[]]; - assert_eq!(xs.split(|x| *x == 1).rev().collect::<Vec<_>>(), splits); - let splits: &[&[_]] = &[&[], &[1, 2, 3, 4]]; - assert_eq!(xs.split(|x| *x == 5).rev().collect::<Vec<_>>(), splits); - let splits: &[&[_]] = &[&[1, 2, 3, 4, 5]]; - assert_eq!(xs.split(|x| *x == 10).rev().collect::<Vec<_>>(), splits); - - let xs: &[i32] = &[]; - let splits: &[&[i32]] = &[&[]]; - assert_eq!(xs.split(|x| *x == 5).rev().collect::<Vec<&[i32]>>(), splits); -} - -#[test] -fn test_rsplitnator() { - let xs = &[1, 2, 3, 4, 5]; - - let splits: &[&[_]] = &[&[1, 2, 3, 4, 5]]; - assert_eq!(xs.rsplitn(1, |x| *x % 2 == 0).collect::<Vec<_>>(), splits); - let splits: &[&[_]] = &[&[5], &[1, 2, 3]]; - assert_eq!(xs.rsplitn(2, |x| *x % 2 == 0).collect::<Vec<_>>(), splits); - let splits: &[&[_]] = &[&[], &[], &[], &[1, 2]]; - assert_eq!(xs.rsplitn(4, |_| true).collect::<Vec<_>>(), splits); - - let xs: &[i32] = &[]; - let splits: &[&[i32]] = &[&[]]; - assert_eq!(xs.rsplitn(2, |x| *x == 5).collect::<Vec<&[i32]>>(), splits); - assert!(xs.rsplitn(0, |x| *x % 2 == 0).next().is_none()); -} - -#[test] -fn test_windowsator() { - let v = &[1, 2, 3, 4]; - - let wins: &[&[_]] = &[&[1, 2], &[2, 3], &[3, 4]]; - assert_eq!(v.windows(2).collect::<Vec<_>>(), wins); - - let wins: &[&[_]] = &[&[1, 2, 3], &[2, 3, 4]]; - assert_eq!(v.windows(3).collect::<Vec<_>>(), wins); - assert!(v.windows(6).next().is_none()); - - let wins: &[&[_]] = &[&[3, 4], &[2, 3], &[1, 2]]; - assert_eq!(v.windows(2).rev().collect::<Vec<&[_]>>(), wins); -} - -#[test] -#[should_panic] -fn test_windowsator_0() { - let v = &[1, 2, 3, 4]; - let _it = v.windows(0); -} - -#[test] -fn test_chunksator() { - let v = &[1, 2, 3, 4, 5]; - - assert_eq!(v.chunks(2).len(), 3); - - let chunks: &[&[_]] = &[&[1, 2], &[3, 4], &[5]]; - assert_eq!(v.chunks(2).collect::<Vec<_>>(), chunks); - let chunks: &[&[_]] = &[&[1, 2, 3], &[4, 5]]; - assert_eq!(v.chunks(3).collect::<Vec<_>>(), chunks); - let chunks: &[&[_]] = &[&[1, 2, 3, 4, 5]]; - assert_eq!(v.chunks(6).collect::<Vec<_>>(), chunks); - - let chunks: &[&[_]] = &[&[5], &[3, 4], &[1, 2]]; - assert_eq!(v.chunks(2).rev().collect::<Vec<_>>(), chunks); -} - -#[test] -#[should_panic] -fn test_chunksator_0() { - let v = &[1, 2, 3, 4]; - let _it = v.chunks(0); -} - -#[test] -fn test_chunks_exactator() { - let v = &[1, 2, 3, 4, 5]; - - assert_eq!(v.chunks_exact(2).len(), 2); - - let chunks: &[&[_]] = &[&[1, 2], &[3, 4]]; - assert_eq!(v.chunks_exact(2).collect::<Vec<_>>(), chunks); - let chunks: &[&[_]] = &[&[1, 2, 3]]; - assert_eq!(v.chunks_exact(3).collect::<Vec<_>>(), chunks); - let chunks: &[&[_]] = &[]; - assert_eq!(v.chunks_exact(6).collect::<Vec<_>>(), chunks); - - let chunks: &[&[_]] = &[&[3, 4], &[1, 2]]; - assert_eq!(v.chunks_exact(2).rev().collect::<Vec<_>>(), chunks); -} - -#[test] -#[should_panic] -fn test_chunks_exactator_0() { - let v = &[1, 2, 3, 4]; - let _it = v.chunks_exact(0); -} - -#[test] -fn test_rchunksator() { - let v = &[1, 2, 3, 4, 5]; - - assert_eq!(v.rchunks(2).len(), 3); - - let chunks: &[&[_]] = &[&[4, 5], &[2, 3], &[1]]; - assert_eq!(v.rchunks(2).collect::<Vec<_>>(), chunks); - let chunks: &[&[_]] = &[&[3, 4, 5], &[1, 2]]; - assert_eq!(v.rchunks(3).collect::<Vec<_>>(), chunks); - let chunks: &[&[_]] = &[&[1, 2, 3, 4, 5]]; - assert_eq!(v.rchunks(6).collect::<Vec<_>>(), chunks); - - let chunks: &[&[_]] = &[&[1], &[2, 3], &[4, 5]]; - assert_eq!(v.rchunks(2).rev().collect::<Vec<_>>(), chunks); -} - -#[test] -#[should_panic] -fn test_rchunksator_0() { - let v = &[1, 2, 3, 4]; - let _it = v.rchunks(0); -} - -#[test] -fn test_rchunks_exactator() { - let v = &[1, 2, 3, 4, 5]; - - assert_eq!(v.rchunks_exact(2).len(), 2); - - let chunks: &[&[_]] = &[&[4, 5], &[2, 3]]; - assert_eq!(v.rchunks_exact(2).collect::<Vec<_>>(), chunks); - let chunks: &[&[_]] = &[&[3, 4, 5]]; - assert_eq!(v.rchunks_exact(3).collect::<Vec<_>>(), chunks); - let chunks: &[&[_]] = &[]; - assert_eq!(v.rchunks_exact(6).collect::<Vec<_>>(), chunks); - - let chunks: &[&[_]] = &[&[2, 3], &[4, 5]]; - assert_eq!(v.rchunks_exact(2).rev().collect::<Vec<_>>(), chunks); -} - -#[test] -#[should_panic] -fn test_rchunks_exactator_0() { - let v = &[1, 2, 3, 4]; - let _it = v.rchunks_exact(0); -} - -#[test] -fn test_reverse_part() { - let mut values = [1, 2, 3, 4, 5]; - values[1..4].reverse(); - assert!(values == [1, 4, 3, 2, 5]); -} - -#[test] -fn test_show() { - macro_rules! test_show_vec { - ($x:expr, $x_str:expr) => {{ - let (x, x_str) = ($x, $x_str); - assert_eq!(format!("{:?}", x), x_str); - assert_eq!(format!("{:?}", x), x_str); - }}; - } - let empty = Vec::<i32>::new(); - test_show_vec!(empty, "[]"); - test_show_vec!(vec![1], "[1]"); - test_show_vec!(vec![1, 2, 3], "[1, 2, 3]"); - test_show_vec!(vec![vec![], vec![1], vec![1, 1]], "[[], [1], [1, 1]]"); - - let empty_mut: &mut [i32] = &mut []; - test_show_vec!(empty_mut, "[]"); - let v = &mut [1]; - test_show_vec!(v, "[1]"); - let v = &mut [1, 2, 3]; - test_show_vec!(v, "[1, 2, 3]"); - let v: &mut [&mut [_]] = &mut [&mut [], &mut [1], &mut [1, 1]]; - test_show_vec!(v, "[[], [1], [1, 1]]"); -} - -#[test] -fn test_vec_default() { - macro_rules! t { - ($ty:ty) => {{ - let v: $ty = Default::default(); - assert!(v.is_empty()); - }}; - } - - t!(&[i32]); - t!(Vec<i32>); -} - -#[test] -#[should_panic] -fn test_overflow_does_not_cause_segfault() { - let mut v = vec![]; - v.reserve_exact(!0); - v.push(1); - v.push(2); -} - -#[test] -#[should_panic] -fn test_overflow_does_not_cause_segfault_managed() { - let mut v = vec![Rc::new(1)]; - v.reserve_exact(!0); - v.push(Rc::new(2)); -} - -#[test] -fn test_mut_split_at() { - let mut values = [1, 2, 3, 4, 5]; - { - let (left, right) = values.split_at_mut(2); - { - let left: &[_] = left; - assert!(left[..left.len()] == [1, 2]); - } - for p in left { - *p += 1; - } - - { - let right: &[_] = right; - assert!(right[..right.len()] == [3, 4, 5]); - } - for p in right { - *p += 2; - } - } - - assert!(values == [2, 3, 5, 6, 7]); -} - -#[derive(Clone, PartialEq)] -struct Foo; - -#[test] -fn test_iter_zero_sized() { - let mut v = vec![Foo, Foo, Foo]; - assert_eq!(v.len(), 3); - let mut cnt = 0; - - for f in &v { - assert!(*f == Foo); - cnt += 1; - } - assert_eq!(cnt, 3); - - for f in &v[1..3] { - assert!(*f == Foo); - cnt += 1; - } - assert_eq!(cnt, 5); - - for f in &mut v { - assert!(*f == Foo); - cnt += 1; - } - assert_eq!(cnt, 8); - - for f in v { - assert!(f == Foo); - cnt += 1; - } - assert_eq!(cnt, 11); - - let xs: [Foo; 3] = [Foo, Foo, Foo]; - cnt = 0; - for f in &xs { - assert!(*f == Foo); - cnt += 1; - } - assert!(cnt == 3); -} - -#[test] -fn test_shrink_to_fit() { - let mut xs = vec![0, 1, 2, 3]; - for i in 4..100 { - xs.push(i) - } - assert_eq!(xs.capacity(), 128); - xs.shrink_to_fit(); - assert_eq!(xs.capacity(), 100); - assert_eq!(xs, (0..100).collect::<Vec<_>>()); -} - -#[test] -fn test_starts_with() { - assert!(b"foobar".starts_with(b"foo")); - assert!(!b"foobar".starts_with(b"oob")); - assert!(!b"foobar".starts_with(b"bar")); - assert!(!b"foo".starts_with(b"foobar")); - assert!(!b"bar".starts_with(b"foobar")); - assert!(b"foobar".starts_with(b"foobar")); - let empty: &[u8] = &[]; - assert!(empty.starts_with(empty)); - assert!(!empty.starts_with(b"foo")); - assert!(b"foobar".starts_with(empty)); -} - -#[test] -fn test_ends_with() { - assert!(b"foobar".ends_with(b"bar")); - assert!(!b"foobar".ends_with(b"oba")); - assert!(!b"foobar".ends_with(b"foo")); - assert!(!b"foo".ends_with(b"foobar")); - assert!(!b"bar".ends_with(b"foobar")); - assert!(b"foobar".ends_with(b"foobar")); - let empty: &[u8] = &[]; - assert!(empty.ends_with(empty)); - assert!(!empty.ends_with(b"foo")); - assert!(b"foobar".ends_with(empty)); -} - -#[test] -fn test_mut_splitator() { - let mut xs = [0, 1, 0, 2, 3, 0, 0, 4, 5, 0]; - assert_eq!(xs.split_mut(|x| *x == 0).count(), 6); - for slice in xs.split_mut(|x| *x == 0) { - slice.reverse(); - } - assert!(xs == [0, 1, 0, 3, 2, 0, 0, 5, 4, 0]); - - let mut xs = [0, 1, 0, 2, 3, 0, 0, 4, 5, 0, 6, 7]; - for slice in xs.split_mut(|x| *x == 0).take(5) { - slice.reverse(); - } - assert!(xs == [0, 1, 0, 3, 2, 0, 0, 5, 4, 0, 6, 7]); -} - -#[test] -fn test_mut_splitator_rev() { - let mut xs = [1, 2, 0, 3, 4, 0, 0, 5, 6, 0]; - for slice in xs.split_mut(|x| *x == 0).rev().take(4) { - slice.reverse(); - } - assert!(xs == [1, 2, 0, 4, 3, 0, 0, 6, 5, 0]); -} - -#[test] -fn test_get_mut() { - let mut v = [0, 1, 2]; - assert_eq!(v.get_mut(3), None); - v.get_mut(1).map(|e| *e = 7); - assert_eq!(v[1], 7); - let mut x = 2; - assert_eq!(v.get_mut(2), Some(&mut x)); -} - -#[test] -fn test_mut_chunks() { - let mut v = [0, 1, 2, 3, 4, 5, 6]; - assert_eq!(v.chunks_mut(3).len(), 3); - for (i, chunk) in v.chunks_mut(3).enumerate() { - for x in chunk { - *x = i as u8; - } - } - let result = [0, 0, 0, 1, 1, 1, 2]; - assert_eq!(v, result); -} - -#[test] -fn test_mut_chunks_rev() { - let mut v = [0, 1, 2, 3, 4, 5, 6]; - for (i, chunk) in v.chunks_mut(3).rev().enumerate() { - for x in chunk { - *x = i as u8; - } - } - let result = [2, 2, 2, 1, 1, 1, 0]; - assert_eq!(v, result); -} - -#[test] -#[should_panic] -fn test_mut_chunks_0() { - let mut v = [1, 2, 3, 4]; - let _it = v.chunks_mut(0); -} - -#[test] -fn test_mut_chunks_exact() { - let mut v = [0, 1, 2, 3, 4, 5, 6]; - assert_eq!(v.chunks_exact_mut(3).len(), 2); - for (i, chunk) in v.chunks_exact_mut(3).enumerate() { - for x in chunk { - *x = i as u8; - } - } - let result = [0, 0, 0, 1, 1, 1, 6]; - assert_eq!(v, result); -} - -#[test] -fn test_mut_chunks_exact_rev() { - let mut v = [0, 1, 2, 3, 4, 5, 6]; - for (i, chunk) in v.chunks_exact_mut(3).rev().enumerate() { - for x in chunk { - *x = i as u8; - } - } - let result = [1, 1, 1, 0, 0, 0, 6]; - assert_eq!(v, result); -} - -#[test] -#[should_panic] -fn test_mut_chunks_exact_0() { - let mut v = [1, 2, 3, 4]; - let _it = v.chunks_exact_mut(0); -} - -#[test] -fn test_mut_rchunks() { - let mut v = [0, 1, 2, 3, 4, 5, 6]; - assert_eq!(v.rchunks_mut(3).len(), 3); - for (i, chunk) in v.rchunks_mut(3).enumerate() { - for x in chunk { - *x = i as u8; - } - } - let result = [2, 1, 1, 1, 0, 0, 0]; - assert_eq!(v, result); -} - -#[test] -fn test_mut_rchunks_rev() { - let mut v = [0, 1, 2, 3, 4, 5, 6]; - for (i, chunk) in v.rchunks_mut(3).rev().enumerate() { - for x in chunk { - *x = i as u8; - } - } - let result = [0, 1, 1, 1, 2, 2, 2]; - assert_eq!(v, result); -} - -#[test] -#[should_panic] -fn test_mut_rchunks_0() { - let mut v = [1, 2, 3, 4]; - let _it = v.rchunks_mut(0); -} - -#[test] -fn test_mut_rchunks_exact() { - let mut v = [0, 1, 2, 3, 4, 5, 6]; - assert_eq!(v.rchunks_exact_mut(3).len(), 2); - for (i, chunk) in v.rchunks_exact_mut(3).enumerate() { - for x in chunk { - *x = i as u8; - } - } - let result = [0, 1, 1, 1, 0, 0, 0]; - assert_eq!(v, result); -} - -#[test] -fn test_mut_rchunks_exact_rev() { - let mut v = [0, 1, 2, 3, 4, 5, 6]; - for (i, chunk) in v.rchunks_exact_mut(3).rev().enumerate() { - for x in chunk { - *x = i as u8; - } - } - let result = [0, 0, 0, 0, 1, 1, 1]; - assert_eq!(v, result); -} - -#[test] -#[should_panic] -fn test_mut_rchunks_exact_0() { - let mut v = [1, 2, 3, 4]; - let _it = v.rchunks_exact_mut(0); -} - -#[test] -fn test_mut_last() { - let mut x = [1, 2, 3, 4, 5]; - let h = x.last_mut(); - assert_eq!(*h.unwrap(), 5); - - let y: &mut [i32] = &mut []; - assert!(y.last_mut().is_none()); -} - -#[test] -fn test_to_vec() { - let xs: Box<_> = box [1, 2, 3]; - let ys = xs.to_vec(); - assert_eq!(ys, [1, 2, 3]); -} - -#[test] -fn test_box_slice_clone() { - let data = vec![vec![0, 1], vec![0], vec![1]]; - let data2 = data.clone().into_boxed_slice().clone().to_vec(); - - assert_eq!(data, data2); -} - -#[test] -#[allow(unused_must_use)] // here, we care about the side effects of `.clone()` -#[cfg_attr(target_os = "emscripten", ignore)] -fn test_box_slice_clone_panics() { - use std::sync::atomic::{AtomicUsize, Ordering}; - use std::sync::Arc; - - struct Canary { - count: Arc<AtomicUsize>, - panics: bool, - } - - impl Drop for Canary { - fn drop(&mut self) { - self.count.fetch_add(1, Ordering::SeqCst); - } - } - - impl Clone for Canary { - fn clone(&self) -> Self { - if self.panics { - panic!() - } - - Canary { count: self.count.clone(), panics: self.panics } - } - } - - let drop_count = Arc::new(AtomicUsize::new(0)); - let canary = Canary { count: drop_count.clone(), panics: false }; - let panic = Canary { count: drop_count.clone(), panics: true }; - - std::panic::catch_unwind(move || { - // When xs is dropped, +5. - let xs = - vec![canary.clone(), canary.clone(), canary.clone(), panic, canary].into_boxed_slice(); - - // When panic is cloned, +3. - xs.clone(); - }) - .unwrap_err(); - - // Total = 8 - assert_eq!(drop_count.load(Ordering::SeqCst), 8); -} - -#[test] -fn test_copy_from_slice() { - let src = [0, 1, 2, 3, 4, 5]; - let mut dst = [0; 6]; - dst.copy_from_slice(&src); - assert_eq!(src, dst) -} - -#[test] -#[should_panic(expected = "destination and source slices have different lengths")] -fn test_copy_from_slice_dst_longer() { - let src = [0, 1, 2, 3]; - let mut dst = [0; 5]; - dst.copy_from_slice(&src); -} - -#[test] -#[should_panic(expected = "destination and source slices have different lengths")] -fn test_copy_from_slice_dst_shorter() { - let src = [0, 1, 2, 3]; - let mut dst = [0; 3]; - dst.copy_from_slice(&src); -} - -const MAX_LEN: usize = 80; - -static DROP_COUNTS: [AtomicUsize; MAX_LEN] = [ - // FIXME(RFC 1109): AtomicUsize is not Copy. - AtomicUsize::new(0), - AtomicUsize::new(0), - AtomicUsize::new(0), - AtomicUsize::new(0), - AtomicUsize::new(0), - AtomicUsize::new(0), - AtomicUsize::new(0), - AtomicUsize::new(0), - AtomicUsize::new(0), - AtomicUsize::new(0), - AtomicUsize::new(0), - AtomicUsize::new(0), - AtomicUsize::new(0), - AtomicUsize::new(0), - AtomicUsize::new(0), - AtomicUsize::new(0), - AtomicUsize::new(0), - AtomicUsize::new(0), - AtomicUsize::new(0), - AtomicUsize::new(0), - AtomicUsize::new(0), - AtomicUsize::new(0), - AtomicUsize::new(0), - AtomicUsize::new(0), - AtomicUsize::new(0), - AtomicUsize::new(0), - AtomicUsize::new(0), - AtomicUsize::new(0), - AtomicUsize::new(0), - AtomicUsize::new(0), - AtomicUsize::new(0), - AtomicUsize::new(0), - AtomicUsize::new(0), - AtomicUsize::new(0), - AtomicUsize::new(0), - AtomicUsize::new(0), - AtomicUsize::new(0), - AtomicUsize::new(0), - AtomicUsize::new(0), - AtomicUsize::new(0), - AtomicUsize::new(0), - AtomicUsize::new(0), - AtomicUsize::new(0), - AtomicUsize::new(0), - AtomicUsize::new(0), - AtomicUsize::new(0), - AtomicUsize::new(0), - AtomicUsize::new(0), - AtomicUsize::new(0), - AtomicUsize::new(0), - AtomicUsize::new(0), - AtomicUsize::new(0), - AtomicUsize::new(0), - AtomicUsize::new(0), - AtomicUsize::new(0), - AtomicUsize::new(0), - AtomicUsize::new(0), - AtomicUsize::new(0), - AtomicUsize::new(0), - AtomicUsize::new(0), - AtomicUsize::new(0), - AtomicUsize::new(0), - AtomicUsize::new(0), - AtomicUsize::new(0), - AtomicUsize::new(0), - AtomicUsize::new(0), - AtomicUsize::new(0), - AtomicUsize::new(0), - AtomicUsize::new(0), - AtomicUsize::new(0), - AtomicUsize::new(0), - AtomicUsize::new(0), - AtomicUsize::new(0), - AtomicUsize::new(0), - AtomicUsize::new(0), - AtomicUsize::new(0), - AtomicUsize::new(0), - AtomicUsize::new(0), - AtomicUsize::new(0), - AtomicUsize::new(0), -]; - -static VERSIONS: AtomicUsize = AtomicUsize::new(0); - -#[derive(Clone, Eq)] -struct DropCounter { - x: u32, - id: usize, - version: Cell<usize>, -} - -impl PartialEq for DropCounter { - fn eq(&self, other: &Self) -> bool { - self.partial_cmp(other) == Some(Ordering::Equal) - } -} - -impl PartialOrd for DropCounter { - fn partial_cmp(&self, other: &Self) -> Option<Ordering> { - self.version.set(self.version.get() + 1); - other.version.set(other.version.get() + 1); - VERSIONS.fetch_add(2, Relaxed); - self.x.partial_cmp(&other.x) - } -} - -impl Ord for DropCounter { - fn cmp(&self, other: &Self) -> Ordering { - self.partial_cmp(other).unwrap() - } -} - -impl Drop for DropCounter { - fn drop(&mut self) { - DROP_COUNTS[self.id].fetch_add(1, Relaxed); - VERSIONS.fetch_sub(self.version.get(), Relaxed); - } -} - -macro_rules! test { - ($input:ident, $func:ident) => { - let len = $input.len(); - - // Work out the total number of comparisons required to sort - // this array... - let mut count = 0usize; - $input.to_owned().$func(|a, b| { - count += 1; - a.cmp(b) - }); - - // ... and then panic on each and every single one. - for panic_countdown in 0..count { - // Refresh the counters. - VERSIONS.store(0, Relaxed); - for i in 0..len { - DROP_COUNTS[i].store(0, Relaxed); - } - - let v = $input.to_owned(); - let _ = std::panic::catch_unwind(move || { - let mut v = v; - let mut panic_countdown = panic_countdown; - v.$func(|a, b| { - if panic_countdown == 0 { - SILENCE_PANIC.with(|s| s.set(true)); - panic!(); - } - panic_countdown -= 1; - a.cmp(b) - }) - }); - - // Check that the number of things dropped is exactly - // what we expect (i.e., the contents of `v`). - for (i, c) in DROP_COUNTS.iter().enumerate().take(len) { - let count = c.load(Relaxed); - assert!(count == 1, "found drop count == {} for i == {}, len == {}", count, i, len); - } - - // Check that the most recent versions of values were dropped. - assert_eq!(VERSIONS.load(Relaxed), 0); - } - }; -} - -thread_local!(static SILENCE_PANIC: Cell<bool> = Cell::new(false)); - -#[test] -#[cfg_attr(target_os = "emscripten", ignore)] // no threads -fn panic_safe() { - let prev = panic::take_hook(); - panic::set_hook(Box::new(move |info| { - if !SILENCE_PANIC.with(|s| s.get()) { - prev(info); - } - })); - - let mut rng = thread_rng(); - - // Miri is too slow - let lens = if cfg!(miri) { (1..10).chain(20..21) } else { (1..20).chain(70..MAX_LEN) }; - let moduli: &[u32] = if cfg!(miri) { &[5] } else { &[5, 20, 50] }; - - for len in lens { - for &modulus in moduli { - for &has_runs in &[false, true] { - let mut input = (0..len) - .map(|id| DropCounter { - x: rng.next_u32() % modulus, - id: id, - version: Cell::new(0), - }) - .collect::<Vec<_>>(); - - if has_runs { - for c in &mut input { - c.x = c.id as u32; - } - - for _ in 0..5 { - let a = rng.gen::<usize>() % len; - let b = rng.gen::<usize>() % len; - if a < b { - input[a..b].reverse(); - } else { - input.swap(a, b); - } - } - } - - test!(input, sort_by); - test!(input, sort_unstable_by); - } - } - } - - // Set default panic hook again. - drop(panic::take_hook()); -} - -#[test] -fn repeat_generic_slice() { - assert_eq!([1, 2].repeat(2), vec![1, 2, 1, 2]); - assert_eq!([1, 2, 3, 4].repeat(0), vec![]); - assert_eq!([1, 2, 3, 4].repeat(1), vec![1, 2, 3, 4]); - assert_eq!([1, 2, 3, 4].repeat(3), vec![1, 2, 3, 4, 1, 2, 3, 4, 1, 2, 3, 4]); -} diff --git a/src/liballoc/tests/str.rs b/src/liballoc/tests/str.rs deleted file mode 100644 index eee98d45340..00000000000 --- a/src/liballoc/tests/str.rs +++ /dev/null @@ -1,1899 +0,0 @@ -use std::borrow::Cow; -use std::cmp::Ordering::{Equal, Greater, Less}; -use std::str::from_utf8; - -#[test] -fn test_le() { - assert!("" <= ""); - assert!("" <= "foo"); - assert!("foo" <= "foo"); - assert_ne!("foo", "bar"); -} - -#[test] -fn test_find() { - assert_eq!("hello".find('l'), Some(2)); - assert_eq!("hello".find(|c: char| c == 'o'), Some(4)); - assert!("hello".find('x').is_none()); - assert!("hello".find(|c: char| c == 'x').is_none()); - assert_eq!("ประเทศไทย中华Việt Nam".find('华'), Some(30)); - assert_eq!("ประเทศไทย中华Việt Nam".find(|c: char| c == '华'), Some(30)); -} - -#[test] -fn test_rfind() { - assert_eq!("hello".rfind('l'), Some(3)); - assert_eq!("hello".rfind(|c: char| c == 'o'), Some(4)); - assert!("hello".rfind('x').is_none()); - assert!("hello".rfind(|c: char| c == 'x').is_none()); - assert_eq!("ประเทศไทย中华Việt Nam".rfind('华'), Some(30)); - assert_eq!("ประเทศไทย中华Việt Nam".rfind(|c: char| c == '华'), Some(30)); -} - -#[test] -fn test_collect() { - let empty = ""; - let s: String = empty.chars().collect(); - assert_eq!(empty, s); - let data = "ประเทศไทย中"; - let s: String = data.chars().collect(); - assert_eq!(data, s); -} - -#[test] -fn test_into_bytes() { - let data = String::from("asdf"); - let buf = data.into_bytes(); - assert_eq!(buf, b"asdf"); -} - -#[test] -fn test_find_str() { - // byte positions - assert_eq!("".find(""), Some(0)); - assert!("banana".find("apple pie").is_none()); - - let data = "abcabc"; - assert_eq!(data[0..6].find("ab"), Some(0)); - assert_eq!(data[2..6].find("ab"), Some(3 - 2)); - assert!(data[2..4].find("ab").is_none()); - - let string = "ประเทศไทย中华Việt Nam"; - let mut data = String::from(string); - data.push_str(string); - assert!(data.find("ไท华").is_none()); - assert_eq!(data[0..43].find(""), Some(0)); - assert_eq!(data[6..43].find(""), Some(6 - 6)); - - assert_eq!(data[0..43].find("ประ"), Some(0)); - assert_eq!(data[0..43].find("ทศไ"), Some(12)); - assert_eq!(data[0..43].find("ย中"), Some(24)); - assert_eq!(data[0..43].find("iệt"), Some(34)); - assert_eq!(data[0..43].find("Nam"), Some(40)); - - assert_eq!(data[43..86].find("ประ"), Some(43 - 43)); - assert_eq!(data[43..86].find("ทศไ"), Some(55 - 43)); - assert_eq!(data[43..86].find("ย中"), Some(67 - 43)); - assert_eq!(data[43..86].find("iệt"), Some(77 - 43)); - assert_eq!(data[43..86].find("Nam"), Some(83 - 43)); - - // find every substring -- assert that it finds it, or an earlier occurrence. - let string = "Việt Namacbaabcaabaaba"; - for (i, ci) in string.char_indices() { - let ip = i + ci.len_utf8(); - for j in string[ip..].char_indices().map(|(i, _)| i).chain(Some(string.len() - ip)) { - let pat = &string[i..ip + j]; - assert!(match string.find(pat) { - None => false, - Some(x) => x <= i, - }); - assert!(match string.rfind(pat) { - None => false, - Some(x) => x >= i, - }); - } - } -} - -fn s(x: &str) -> String { - x.to_string() -} - -macro_rules! test_concat { - ($expected: expr, $string: expr) => {{ - let s: String = $string.concat(); - assert_eq!($expected, s); - }}; -} - -#[test] -fn test_concat_for_different_types() { - test_concat!("ab", vec![s("a"), s("b")]); - test_concat!("ab", vec!["a", "b"]); -} - -#[test] -fn test_concat_for_different_lengths() { - let empty: &[&str] = &[]; - test_concat!("", empty); - test_concat!("a", ["a"]); - test_concat!("ab", ["a", "b"]); - test_concat!("abc", ["", "a", "bc"]); -} - -macro_rules! test_join { - ($expected: expr, $string: expr, $delim: expr) => {{ - let s = $string.join($delim); - assert_eq!($expected, s); - }}; -} - -#[test] -fn test_join_for_different_types() { - test_join!("a-b", ["a", "b"], "-"); - let hyphen = "-".to_string(); - test_join!("a-b", [s("a"), s("b")], &*hyphen); - test_join!("a-b", vec!["a", "b"], &*hyphen); - test_join!("a-b", &*vec!["a", "b"], "-"); - test_join!("a-b", vec![s("a"), s("b")], "-"); -} - -#[test] -fn test_join_for_different_lengths() { - let empty: &[&str] = &[]; - test_join!("", empty, "-"); - test_join!("a", ["a"], "-"); - test_join!("a-b", ["a", "b"], "-"); - test_join!("-a-bc", ["", "a", "bc"], "-"); -} - -// join has fast paths for small separators up to 4 bytes -// this tests the slow paths. -#[test] -fn test_join_for_different_lengths_with_long_separator() { - assert_eq!("~~~~~".len(), 15); - - let empty: &[&str] = &[]; - test_join!("", empty, "~~~~~"); - test_join!("a", ["a"], "~~~~~"); - test_join!("a~~~~~b", ["a", "b"], "~~~~~"); - test_join!("~~~~~a~~~~~bc", ["", "a", "bc"], "~~~~~"); -} - -#[test] -#[cfg_attr(miri, ignore)] // Miri is too slow -fn test_unsafe_slice() { - assert_eq!("ab", unsafe { "abc".get_unchecked(0..2) }); - assert_eq!("bc", unsafe { "abc".get_unchecked(1..3) }); - assert_eq!("", unsafe { "abc".get_unchecked(1..1) }); - fn a_million_letter_a() -> String { - let mut i = 0; - let mut rs = String::new(); - while i < 100000 { - rs.push_str("aaaaaaaaaa"); - i += 1; - } - rs - } - fn half_a_million_letter_a() -> String { - let mut i = 0; - let mut rs = String::new(); - while i < 100000 { - rs.push_str("aaaaa"); - i += 1; - } - rs - } - let letters = a_million_letter_a(); - assert_eq!(half_a_million_letter_a(), unsafe { letters.get_unchecked(0..500000) }); -} - -#[test] -fn test_starts_with() { - assert!("".starts_with("")); - assert!("abc".starts_with("")); - assert!("abc".starts_with("a")); - assert!(!"a".starts_with("abc")); - assert!(!"".starts_with("abc")); - assert!(!"ödd".starts_with("-")); - assert!("ödd".starts_with("öd")); -} - -#[test] -fn test_ends_with() { - assert!("".ends_with("")); - assert!("abc".ends_with("")); - assert!("abc".ends_with("c")); - assert!(!"a".ends_with("abc")); - assert!(!"".ends_with("abc")); - assert!(!"ddö".ends_with("-")); - assert!("ddö".ends_with("dö")); -} - -#[test] -fn test_is_empty() { - assert!("".is_empty()); - assert!(!"a".is_empty()); -} - -#[test] -fn test_replacen() { - assert_eq!("".replacen('a', "b", 5), ""); - assert_eq!("acaaa".replacen("a", "b", 3), "bcbba"); - assert_eq!("aaaa".replacen("a", "b", 0), "aaaa"); - - let test = "test"; - assert_eq!(" test test ".replacen(test, "toast", 3), " toast toast "); - assert_eq!(" test test ".replacen(test, "toast", 0), " test test "); - assert_eq!(" test test ".replacen(test, "", 5), " "); - - assert_eq!("qwer123zxc789".replacen(char::is_numeric, "", 3), "qwerzxc789"); -} - -#[test] -fn test_replace() { - let a = "a"; - assert_eq!("".replace(a, "b"), ""); - assert_eq!("a".replace(a, "b"), "b"); - assert_eq!("ab".replace(a, "b"), "bb"); - let test = "test"; - assert_eq!(" test test ".replace(test, "toast"), " toast toast "); - assert_eq!(" test test ".replace(test, ""), " "); -} - -#[test] -fn test_replace_2a() { - let data = "ประเทศไทย中华"; - let repl = "دولة الكويت"; - - let a = "ประเ"; - let a2 = "دولة الكويتทศไทย中华"; - assert_eq!(data.replace(a, repl), a2); -} - -#[test] -fn test_replace_2b() { - let data = "ประเทศไทย中华"; - let repl = "دولة الكويت"; - - let b = "ะเ"; - let b2 = "ปรدولة الكويتทศไทย中华"; - assert_eq!(data.replace(b, repl), b2); -} - -#[test] -fn test_replace_2c() { - let data = "ประเทศไทย中华"; - let repl = "دولة الكويت"; - - let c = "中华"; - let c2 = "ประเทศไทยدولة الكويت"; - assert_eq!(data.replace(c, repl), c2); -} - -#[test] -fn test_replace_2d() { - let data = "ประเทศไทย中华"; - let repl = "دولة الكويت"; - - let d = "ไท华"; - assert_eq!(data.replace(d, repl), data); -} - -#[test] -fn test_replace_pattern() { - let data = "abcdαβγδabcdαβγδ"; - assert_eq!(data.replace("dαβ", "😺😺😺"), "abc😺😺😺γδabc😺😺😺γδ"); - assert_eq!(data.replace('γ', "😺😺😺"), "abcdαβ😺😺😺δabcdαβ😺😺😺δ"); - assert_eq!(data.replace(&['a', 'γ'] as &[_], "😺😺😺"), "😺😺😺bcdαβ😺😺😺δ😺😺😺bcdαβ😺😺😺δ"); - assert_eq!(data.replace(|c| c == 'γ', "😺😺😺"), "abcdαβ😺😺😺δabcdαβ😺😺😺δ"); -} - -// The current implementation of SliceIndex fails to handle methods -// orthogonally from range types; therefore, it is worth testing -// all of the indexing operations on each input. -mod slice_index { - // Test a slicing operation **that should succeed,** - // testing it on all of the indexing methods. - // - // This is not suitable for testing failure on invalid inputs. - macro_rules! assert_range_eq { - ($s:expr, $range:expr, $expected:expr) => { - let mut s: String = $s.to_owned(); - let mut expected: String = $expected.to_owned(); - { - let s: &str = &s; - let expected: &str = &expected; - - assert_eq!(&s[$range], expected, "(in assertion for: index)"); - assert_eq!(s.get($range), Some(expected), "(in assertion for: get)"); - unsafe { - assert_eq!( - s.get_unchecked($range), - expected, - "(in assertion for: get_unchecked)", - ); - } - } - { - let s: &mut str = &mut s; - let expected: &mut str = &mut expected; - - assert_eq!(&mut s[$range], expected, "(in assertion for: index_mut)",); - assert_eq!( - s.get_mut($range), - Some(&mut expected[..]), - "(in assertion for: get_mut)", - ); - unsafe { - assert_eq!( - s.get_unchecked_mut($range), - expected, - "(in assertion for: get_unchecked_mut)", - ); - } - } - }; - } - - // Make sure the macro can actually detect bugs, - // because if it can't, then what are we even doing here? - // - // (Be aware this only demonstrates the ability to detect bugs - // in the FIRST method that panics, as the macro is not designed - // to be used in `should_panic`) - #[test] - #[should_panic(expected = "out of bounds")] - fn assert_range_eq_can_fail_by_panic() { - assert_range_eq!("abc", 0..5, "abc"); - } - - // (Be aware this only demonstrates the ability to detect bugs - // in the FIRST method it calls, as the macro is not designed - // to be used in `should_panic`) - #[test] - #[should_panic(expected = "==")] - fn assert_range_eq_can_fail_by_inequality() { - assert_range_eq!("abc", 0..2, "abc"); - } - - // Generates test cases for bad index operations. - // - // This generates `should_panic` test cases for Index/IndexMut - // and `None` test cases for get/get_mut. - macro_rules! panic_cases { - ($( - in mod $case_name:ident { - data: $data:expr; - - // optional: - // - // a similar input for which DATA[input] succeeds, and the corresponding - // output str. This helps validate "critical points" where an input range - // straddles the boundary between valid and invalid. - // (such as the input `len..len`, which is just barely valid) - $( - good: data[$good:expr] == $output:expr; - )* - - bad: data[$bad:expr]; - message: $expect_msg:expr; // must be a literal - } - )*) => {$( - mod $case_name { - #[test] - fn pass() { - let mut v: String = $data.into(); - - $( assert_range_eq!(v, $good, $output); )* - - { - let v: &str = &v; - assert_eq!(v.get($bad), None, "(in None assertion for get)"); - } - - { - let v: &mut str = &mut v; - assert_eq!(v.get_mut($bad), None, "(in None assertion for get_mut)"); - } - } - - #[test] - #[should_panic(expected = $expect_msg)] - fn index_fail() { - let v: String = $data.into(); - let v: &str = &v; - let _v = &v[$bad]; - } - - #[test] - #[should_panic(expected = $expect_msg)] - fn index_mut_fail() { - let mut v: String = $data.into(); - let v: &mut str = &mut v; - let _v = &mut v[$bad]; - } - } - )*}; - } - - #[test] - fn simple_ascii() { - assert_range_eq!("abc", .., "abc"); - - assert_range_eq!("abc", 0..2, "ab"); - assert_range_eq!("abc", 0..=1, "ab"); - assert_range_eq!("abc", ..2, "ab"); - assert_range_eq!("abc", ..=1, "ab"); - - assert_range_eq!("abc", 1..3, "bc"); - assert_range_eq!("abc", 1..=2, "bc"); - assert_range_eq!("abc", 1..1, ""); - assert_range_eq!("abc", 1..=0, ""); - } - - #[test] - fn simple_unicode() { - // 日本 - assert_range_eq!("\u{65e5}\u{672c}", .., "\u{65e5}\u{672c}"); - - assert_range_eq!("\u{65e5}\u{672c}", 0..3, "\u{65e5}"); - assert_range_eq!("\u{65e5}\u{672c}", 0..=2, "\u{65e5}"); - assert_range_eq!("\u{65e5}\u{672c}", ..3, "\u{65e5}"); - assert_range_eq!("\u{65e5}\u{672c}", ..=2, "\u{65e5}"); - - assert_range_eq!("\u{65e5}\u{672c}", 3..6, "\u{672c}"); - assert_range_eq!("\u{65e5}\u{672c}", 3..=5, "\u{672c}"); - assert_range_eq!("\u{65e5}\u{672c}", 3.., "\u{672c}"); - - let data = "ประเทศไทย中华"; - assert_range_eq!(data, 0..3, "ป"); - assert_range_eq!(data, 3..6, "ร"); - assert_range_eq!(data, 3..3, ""); - assert_range_eq!(data, 30..33, "华"); - - /*0: 中 - 3: 华 - 6: V - 7: i - 8: ệ - 11: t - 12: - 13: N - 14: a - 15: m */ - let ss = "中华Việt Nam"; - assert_range_eq!(ss, 3..6, "华"); - assert_range_eq!(ss, 6..16, "Việt Nam"); - assert_range_eq!(ss, 6..=15, "Việt Nam"); - assert_range_eq!(ss, 6.., "Việt Nam"); - - assert_range_eq!(ss, 0..3, "中"); - assert_range_eq!(ss, 3..7, "华V"); - assert_range_eq!(ss, 3..=6, "华V"); - assert_range_eq!(ss, 3..3, ""); - assert_range_eq!(ss, 3..=2, ""); - } - - #[test] - #[cfg_attr(target_os = "emscripten", ignore)] // hits an OOM - #[cfg_attr(miri, ignore)] // Miri is too slow - fn simple_big() { - fn a_million_letter_x() -> String { - let mut i = 0; - let mut rs = String::new(); - while i < 100000 { - rs.push_str("华华华华华华华华华华"); - i += 1; - } - rs - } - fn half_a_million_letter_x() -> String { - let mut i = 0; - let mut rs = String::new(); - while i < 100000 { - rs.push_str("华华华华华"); - i += 1; - } - rs - } - let letters = a_million_letter_x(); - assert_range_eq!(letters, 0..3 * 500000, half_a_million_letter_x()); - } - - #[test] - #[should_panic] - fn test_slice_fail() { - &"中华Việt Nam"[0..2]; - } - - panic_cases! { - in mod rangefrom_len { - data: "abcdef"; - good: data[6..] == ""; - bad: data[7..]; - message: "out of bounds"; - } - - in mod rangeto_len { - data: "abcdef"; - good: data[..6] == "abcdef"; - bad: data[..7]; - message: "out of bounds"; - } - - in mod rangetoinclusive_len { - data: "abcdef"; - good: data[..=5] == "abcdef"; - bad: data[..=6]; - message: "out of bounds"; - } - - in mod range_len_len { - data: "abcdef"; - good: data[6..6] == ""; - bad: data[7..7]; - message: "out of bounds"; - } - - in mod rangeinclusive_len_len { - data: "abcdef"; - good: data[6..=5] == ""; - bad: data[7..=6]; - message: "out of bounds"; - } - } - - panic_cases! { - in mod range_neg_width { - data: "abcdef"; - good: data[4..4] == ""; - bad: data[4..3]; - message: "begin <= end (4 <= 3)"; - } - - in mod rangeinclusive_neg_width { - data: "abcdef"; - good: data[4..=3] == ""; - bad: data[4..=2]; - message: "begin <= end (4 <= 3)"; - } - } - - mod overflow { - panic_cases! { - in mod rangeinclusive { - data: "hello"; - // note: using 0 specifically ensures that the result of overflowing is 0..0, - // so that `get` doesn't simply return None for the wrong reason. - bad: data[0..=usize::MAX]; - message: "maximum usize"; - } - - in mod rangetoinclusive { - data: "hello"; - bad: data[..=usize::MAX]; - message: "maximum usize"; - } - } - } - - mod boundary { - const DATA: &str = "abcαβγ"; - - const BAD_START: usize = 4; - const GOOD_START: usize = 3; - const BAD_END: usize = 6; - const GOOD_END: usize = 7; - const BAD_END_INCL: usize = BAD_END - 1; - const GOOD_END_INCL: usize = GOOD_END - 1; - - // it is especially important to test all of the different range types here - // because some of the logic may be duplicated as part of micro-optimizations - // to dodge unicode boundary checks on half-ranges. - panic_cases! { - in mod range_1 { - data: super::DATA; - bad: data[super::BAD_START..super::GOOD_END]; - message: - "byte index 4 is not a char boundary; it is inside 'α' (bytes 3..5) of"; - } - - in mod range_2 { - data: super::DATA; - bad: data[super::GOOD_START..super::BAD_END]; - message: - "byte index 6 is not a char boundary; it is inside 'β' (bytes 5..7) of"; - } - - in mod rangefrom { - data: super::DATA; - bad: data[super::BAD_START..]; - message: - "byte index 4 is not a char boundary; it is inside 'α' (bytes 3..5) of"; - } - - in mod rangeto { - data: super::DATA; - bad: data[..super::BAD_END]; - message: - "byte index 6 is not a char boundary; it is inside 'β' (bytes 5..7) of"; - } - - in mod rangeinclusive_1 { - data: super::DATA; - bad: data[super::BAD_START..=super::GOOD_END_INCL]; - message: - "byte index 4 is not a char boundary; it is inside 'α' (bytes 3..5) of"; - } - - in mod rangeinclusive_2 { - data: super::DATA; - bad: data[super::GOOD_START..=super::BAD_END_INCL]; - message: - "byte index 6 is not a char boundary; it is inside 'β' (bytes 5..7) of"; - } - - in mod rangetoinclusive { - data: super::DATA; - bad: data[..=super::BAD_END_INCL]; - message: - "byte index 6 is not a char boundary; it is inside 'β' (bytes 5..7) of"; - } - } - } - - const LOREM_PARAGRAPH: &str = "\ - Lorem ipsum dolor sit amet, consectetur adipiscing elit. Suspendisse quis lorem \ - sit amet dolor ultricies condimentum. Praesent iaculis purus elit, ac malesuada \ - quam malesuada in. Duis sed orci eros. Suspendisse sit amet magna mollis, mollis \ - nunc luctus, imperdiet mi. Integer fringilla non sem ut lacinia. Fusce varius \ - tortor a risus porttitor hendrerit. Morbi mauris dui, ultricies nec tempus vel, \ - gravida nec quam."; - - // check the panic includes the prefix of the sliced string - #[test] - #[should_panic(expected = "byte index 1024 is out of bounds of `Lorem ipsum dolor sit amet")] - fn test_slice_fail_truncated_1() { - &LOREM_PARAGRAPH[..1024]; - } - // check the truncation in the panic message - #[test] - #[should_panic(expected = "luctus, im`[...]")] - fn test_slice_fail_truncated_2() { - &LOREM_PARAGRAPH[..1024]; - } -} - -#[test] -fn test_str_slice_rangetoinclusive_ok() { - let s = "abcαβγ"; - assert_eq!(&s[..=2], "abc"); - assert_eq!(&s[..=4], "abcα"); -} - -#[test] -#[should_panic] -fn test_str_slice_rangetoinclusive_notok() { - let s = "abcαβγ"; - &s[..=3]; -} - -#[test] -fn test_str_slicemut_rangetoinclusive_ok() { - let mut s = "abcαβγ".to_owned(); - let s: &mut str = &mut s; - assert_eq!(&mut s[..=2], "abc"); - assert_eq!(&mut s[..=4], "abcα"); -} - -#[test] -#[should_panic] -fn test_str_slicemut_rangetoinclusive_notok() { - let mut s = "abcαβγ".to_owned(); - let s: &mut str = &mut s; - &mut s[..=3]; -} - -#[test] -fn test_is_char_boundary() { - let s = "ศไทย中华Việt Nam β-release 🐱123"; - assert!(s.is_char_boundary(0)); - assert!(s.is_char_boundary(s.len())); - assert!(!s.is_char_boundary(s.len() + 1)); - for (i, ch) in s.char_indices() { - // ensure character locations are boundaries and continuation bytes are not - assert!(s.is_char_boundary(i), "{} is a char boundary in {:?}", i, s); - for j in 1..ch.len_utf8() { - assert!( - !s.is_char_boundary(i + j), - "{} should not be a char boundary in {:?}", - i + j, - s - ); - } - } -} - -#[test] -fn test_trim_start_matches() { - let v: &[char] = &[]; - assert_eq!(" *** foo *** ".trim_start_matches(v), " *** foo *** "); - let chars: &[char] = &['*', ' ']; - assert_eq!(" *** foo *** ".trim_start_matches(chars), "foo *** "); - assert_eq!(" *** *** ".trim_start_matches(chars), ""); - assert_eq!("foo *** ".trim_start_matches(chars), "foo *** "); - - assert_eq!("11foo1bar11".trim_start_matches('1'), "foo1bar11"); - let chars: &[char] = &['1', '2']; - assert_eq!("12foo1bar12".trim_start_matches(chars), "foo1bar12"); - assert_eq!("123foo1bar123".trim_start_matches(|c: char| c.is_numeric()), "foo1bar123"); -} - -#[test] -fn test_trim_end_matches() { - let v: &[char] = &[]; - assert_eq!(" *** foo *** ".trim_end_matches(v), " *** foo *** "); - let chars: &[char] = &['*', ' ']; - assert_eq!(" *** foo *** ".trim_end_matches(chars), " *** foo"); - assert_eq!(" *** *** ".trim_end_matches(chars), ""); - assert_eq!(" *** foo".trim_end_matches(chars), " *** foo"); - - assert_eq!("11foo1bar11".trim_end_matches('1'), "11foo1bar"); - let chars: &[char] = &['1', '2']; - assert_eq!("12foo1bar12".trim_end_matches(chars), "12foo1bar"); - assert_eq!("123foo1bar123".trim_end_matches(|c: char| c.is_numeric()), "123foo1bar"); -} - -#[test] -fn test_trim_matches() { - let v: &[char] = &[]; - assert_eq!(" *** foo *** ".trim_matches(v), " *** foo *** "); - let chars: &[char] = &['*', ' ']; - assert_eq!(" *** foo *** ".trim_matches(chars), "foo"); - assert_eq!(" *** *** ".trim_matches(chars), ""); - assert_eq!("foo".trim_matches(chars), "foo"); - - assert_eq!("11foo1bar11".trim_matches('1'), "foo1bar"); - let chars: &[char] = &['1', '2']; - assert_eq!("12foo1bar12".trim_matches(chars), "foo1bar"); - assert_eq!("123foo1bar123".trim_matches(|c: char| c.is_numeric()), "foo1bar"); -} - -#[test] -fn test_trim_start() { - assert_eq!("".trim_start(), ""); - assert_eq!("a".trim_start(), "a"); - assert_eq!(" ".trim_start(), ""); - assert_eq!(" blah".trim_start(), "blah"); - assert_eq!(" \u{3000} wut".trim_start(), "wut"); - assert_eq!("hey ".trim_start(), "hey "); -} - -#[test] -fn test_trim_end() { - assert_eq!("".trim_end(), ""); - assert_eq!("a".trim_end(), "a"); - assert_eq!(" ".trim_end(), ""); - assert_eq!("blah ".trim_end(), "blah"); - assert_eq!("wut \u{3000} ".trim_end(), "wut"); - assert_eq!(" hey".trim_end(), " hey"); -} - -#[test] -fn test_trim() { - assert_eq!("".trim(), ""); - assert_eq!("a".trim(), "a"); - assert_eq!(" ".trim(), ""); - assert_eq!(" blah ".trim(), "blah"); - assert_eq!("\nwut \u{3000} ".trim(), "wut"); - assert_eq!(" hey dude ".trim(), "hey dude"); -} - -#[test] -fn test_is_whitespace() { - assert!("".chars().all(|c| c.is_whitespace())); - assert!(" ".chars().all(|c| c.is_whitespace())); - assert!("\u{2009}".chars().all(|c| c.is_whitespace())); // Thin space - assert!(" \n\t ".chars().all(|c| c.is_whitespace())); - assert!(!" _ ".chars().all(|c| c.is_whitespace())); -} - -#[test] -fn test_is_utf8() { - // deny overlong encodings - assert!(from_utf8(&[0xc0, 0x80]).is_err()); - assert!(from_utf8(&[0xc0, 0xae]).is_err()); - assert!(from_utf8(&[0xe0, 0x80, 0x80]).is_err()); - assert!(from_utf8(&[0xe0, 0x80, 0xaf]).is_err()); - assert!(from_utf8(&[0xe0, 0x81, 0x81]).is_err()); - assert!(from_utf8(&[0xf0, 0x82, 0x82, 0xac]).is_err()); - assert!(from_utf8(&[0xf4, 0x90, 0x80, 0x80]).is_err()); - - // deny surrogates - assert!(from_utf8(&[0xED, 0xA0, 0x80]).is_err()); - assert!(from_utf8(&[0xED, 0xBF, 0xBF]).is_err()); - - assert!(from_utf8(&[0xC2, 0x80]).is_ok()); - assert!(from_utf8(&[0xDF, 0xBF]).is_ok()); - assert!(from_utf8(&[0xE0, 0xA0, 0x80]).is_ok()); - assert!(from_utf8(&[0xED, 0x9F, 0xBF]).is_ok()); - assert!(from_utf8(&[0xEE, 0x80, 0x80]).is_ok()); - assert!(from_utf8(&[0xEF, 0xBF, 0xBF]).is_ok()); - assert!(from_utf8(&[0xF0, 0x90, 0x80, 0x80]).is_ok()); - assert!(from_utf8(&[0xF4, 0x8F, 0xBF, 0xBF]).is_ok()); -} - -#[test] -fn from_utf8_mostly_ascii() { - // deny invalid bytes embedded in long stretches of ascii - for i in 32..64 { - let mut data = [0; 128]; - data[i] = 0xC0; - assert!(from_utf8(&data).is_err()); - data[i] = 0xC2; - assert!(from_utf8(&data).is_err()); - } -} - -#[test] -fn from_utf8_error() { - macro_rules! test { - ($input: expr, $expected_valid_up_to: expr, $expected_error_len: expr) => { - let error = from_utf8($input).unwrap_err(); - assert_eq!(error.valid_up_to(), $expected_valid_up_to); - assert_eq!(error.error_len(), $expected_error_len); - }; - } - test!(b"A\xC3\xA9 \xFF ", 4, Some(1)); - test!(b"A\xC3\xA9 \x80 ", 4, Some(1)); - test!(b"A\xC3\xA9 \xC1 ", 4, Some(1)); - test!(b"A\xC3\xA9 \xC1", 4, Some(1)); - test!(b"A\xC3\xA9 \xC2", 4, None); - test!(b"A\xC3\xA9 \xC2 ", 4, Some(1)); - test!(b"A\xC3\xA9 \xC2\xC0", 4, Some(1)); - test!(b"A\xC3\xA9 \xE0", 4, None); - test!(b"A\xC3\xA9 \xE0\x9F", 4, Some(1)); - test!(b"A\xC3\xA9 \xE0\xA0", 4, None); - test!(b"A\xC3\xA9 \xE0\xA0\xC0", 4, Some(2)); - test!(b"A\xC3\xA9 \xE0\xA0 ", 4, Some(2)); - test!(b"A\xC3\xA9 \xED\xA0\x80 ", 4, Some(1)); - test!(b"A\xC3\xA9 \xF1", 4, None); - test!(b"A\xC3\xA9 \xF1\x80", 4, None); - test!(b"A\xC3\xA9 \xF1\x80\x80", 4, None); - test!(b"A\xC3\xA9 \xF1 ", 4, Some(1)); - test!(b"A\xC3\xA9 \xF1\x80 ", 4, Some(2)); - test!(b"A\xC3\xA9 \xF1\x80\x80 ", 4, Some(3)); -} - -#[test] -fn test_as_bytes() { - // no null - let v = [ - 224, 184, 168, 224, 185, 132, 224, 184, 151, 224, 184, 162, 228, 184, 173, 229, 141, 142, - 86, 105, 225, 187, 135, 116, 32, 78, 97, 109, - ]; - let b: &[u8] = &[]; - assert_eq!("".as_bytes(), b); - assert_eq!("abc".as_bytes(), b"abc"); - assert_eq!("ศไทย中华Việt Nam".as_bytes(), v); -} - -#[test] -#[should_panic] -fn test_as_bytes_fail() { - // Don't double free. (I'm not sure if this exercises the - // original problem code path anymore.) - let s = String::from(""); - let _bytes = s.as_bytes(); - panic!(); -} - -#[test] -fn test_as_ptr() { - let buf = "hello".as_ptr(); - unsafe { - assert_eq!(*buf.offset(0), b'h'); - assert_eq!(*buf.offset(1), b'e'); - assert_eq!(*buf.offset(2), b'l'); - assert_eq!(*buf.offset(3), b'l'); - assert_eq!(*buf.offset(4), b'o'); - } -} - -#[test] -fn vec_str_conversions() { - let s1: String = String::from("All mimsy were the borogoves"); - - let v: Vec<u8> = s1.as_bytes().to_vec(); - let s2: String = String::from(from_utf8(&v).unwrap()); - let mut i = 0; - let n1 = s1.len(); - let n2 = v.len(); - assert_eq!(n1, n2); - while i < n1 { - let a: u8 = s1.as_bytes()[i]; - let b: u8 = s2.as_bytes()[i]; - assert_eq!(a, b); - i += 1; - } -} - -#[test] -fn test_contains() { - assert!("abcde".contains("bcd")); - assert!("abcde".contains("abcd")); - assert!("abcde".contains("bcde")); - assert!("abcde".contains("")); - assert!("".contains("")); - assert!(!"abcde".contains("def")); - assert!(!"".contains("a")); - - let data = "ประเทศไทย中华Việt Nam"; - assert!(data.contains("ประเ")); - assert!(data.contains("ะเ")); - assert!(data.contains("中华")); - assert!(!data.contains("ไท华")); -} - -#[test] -fn test_contains_char() { - assert!("abc".contains('b')); - assert!("a".contains('a')); - assert!(!"abc".contains('d')); - assert!(!"".contains('a')); -} - -#[test] -fn test_split_at() { - let s = "ศไทย中华Việt Nam"; - for (index, _) in s.char_indices() { - let (a, b) = s.split_at(index); - assert_eq!(&s[..a.len()], a); - assert_eq!(&s[a.len()..], b); - } - let (a, b) = s.split_at(s.len()); - assert_eq!(a, s); - assert_eq!(b, ""); -} - -#[test] -fn test_split_at_mut() { - let mut s = "Hello World".to_string(); - { - let (a, b) = s.split_at_mut(5); - a.make_ascii_uppercase(); - b.make_ascii_lowercase(); - } - assert_eq!(s, "HELLO world"); -} - -#[test] -#[should_panic] -fn test_split_at_boundscheck() { - let s = "ศไทย中华Việt Nam"; - s.split_at(1); -} - -#[test] -fn test_escape_unicode() { - assert_eq!("abc".escape_unicode().to_string(), "\\u{61}\\u{62}\\u{63}"); - assert_eq!("a c".escape_unicode().to_string(), "\\u{61}\\u{20}\\u{63}"); - assert_eq!("\r\n\t".escape_unicode().to_string(), "\\u{d}\\u{a}\\u{9}"); - assert_eq!("'\"\\".escape_unicode().to_string(), "\\u{27}\\u{22}\\u{5c}"); - assert_eq!("\x00\x01\u{fe}\u{ff}".escape_unicode().to_string(), "\\u{0}\\u{1}\\u{fe}\\u{ff}"); - assert_eq!("\u{100}\u{ffff}".escape_unicode().to_string(), "\\u{100}\\u{ffff}"); - assert_eq!("\u{10000}\u{10ffff}".escape_unicode().to_string(), "\\u{10000}\\u{10ffff}"); - assert_eq!("ab\u{fb00}".escape_unicode().to_string(), "\\u{61}\\u{62}\\u{fb00}"); - assert_eq!("\u{1d4ea}\r".escape_unicode().to_string(), "\\u{1d4ea}\\u{d}"); -} - -#[test] -fn test_escape_debug() { - // Note that there are subtleties with the number of backslashes - // on the left- and right-hand sides. In particular, Unicode code points - // are usually escaped with two backslashes on the right-hand side, as - // they are escaped. However, when the character is unescaped (e.g., for - // printable characters), only a single backslash appears (as the character - // itself appears in the debug string). - assert_eq!("abc".escape_debug().to_string(), "abc"); - assert_eq!("a c".escape_debug().to_string(), "a c"); - assert_eq!("éèê".escape_debug().to_string(), "éèê"); - assert_eq!("\r\n\t".escape_debug().to_string(), "\\r\\n\\t"); - assert_eq!("'\"\\".escape_debug().to_string(), "\\'\\\"\\\\"); - assert_eq!("\u{7f}\u{ff}".escape_debug().to_string(), "\\u{7f}\u{ff}"); - assert_eq!("\u{100}\u{ffff}".escape_debug().to_string(), "\u{100}\\u{ffff}"); - assert_eq!("\u{10000}\u{10ffff}".escape_debug().to_string(), "\u{10000}\\u{10ffff}"); - assert_eq!("ab\u{200b}".escape_debug().to_string(), "ab\\u{200b}"); - assert_eq!("\u{10d4ea}\r".escape_debug().to_string(), "\\u{10d4ea}\\r"); - assert_eq!( - "\u{301}a\u{301}bé\u{e000}".escape_debug().to_string(), - "\\u{301}a\u{301}bé\\u{e000}" - ); -} - -#[test] -fn test_escape_default() { - assert_eq!("abc".escape_default().to_string(), "abc"); - assert_eq!("a c".escape_default().to_string(), "a c"); - assert_eq!("éèê".escape_default().to_string(), "\\u{e9}\\u{e8}\\u{ea}"); - assert_eq!("\r\n\t".escape_default().to_string(), "\\r\\n\\t"); - assert_eq!("'\"\\".escape_default().to_string(), "\\'\\\"\\\\"); - assert_eq!("\u{7f}\u{ff}".escape_default().to_string(), "\\u{7f}\\u{ff}"); - assert_eq!("\u{100}\u{ffff}".escape_default().to_string(), "\\u{100}\\u{ffff}"); - assert_eq!("\u{10000}\u{10ffff}".escape_default().to_string(), "\\u{10000}\\u{10ffff}"); - assert_eq!("ab\u{200b}".escape_default().to_string(), "ab\\u{200b}"); - assert_eq!("\u{10d4ea}\r".escape_default().to_string(), "\\u{10d4ea}\\r"); -} - -#[test] -fn test_total_ord() { - assert_eq!("1234".cmp("123"), Greater); - assert_eq!("123".cmp("1234"), Less); - assert_eq!("1234".cmp("1234"), Equal); - assert_eq!("12345555".cmp("123456"), Less); - assert_eq!("22".cmp("1234"), Greater); -} - -#[test] -fn test_iterator() { - let s = "ศไทย中华Việt Nam"; - let v = ['ศ', 'ไ', 'ท', 'ย', '中', '华', 'V', 'i', 'ệ', 't', ' ', 'N', 'a', 'm']; - - let mut pos = 0; - let it = s.chars(); - - for c in it { - assert_eq!(c, v[pos]); - pos += 1; - } - assert_eq!(pos, v.len()); - assert_eq!(s.chars().count(), v.len()); -} - -#[test] -fn test_rev_iterator() { - let s = "ศไทย中华Việt Nam"; - let v = ['m', 'a', 'N', ' ', 't', 'ệ', 'i', 'V', '华', '中', 'ย', 'ท', 'ไ', 'ศ']; - - let mut pos = 0; - let it = s.chars().rev(); - - for c in it { - assert_eq!(c, v[pos]); - pos += 1; - } - assert_eq!(pos, v.len()); -} - -#[test] -#[cfg_attr(miri, ignore)] // Miri is too slow -fn test_chars_decoding() { - let mut bytes = [0; 4]; - for c in (0..0x110000).filter_map(std::char::from_u32) { - let s = c.encode_utf8(&mut bytes); - if Some(c) != s.chars().next() { - panic!("character {:x}={} does not decode correctly", c as u32, c); - } - } -} - -#[test] -#[cfg_attr(miri, ignore)] // Miri is too slow -fn test_chars_rev_decoding() { - let mut bytes = [0; 4]; - for c in (0..0x110000).filter_map(std::char::from_u32) { - let s = c.encode_utf8(&mut bytes); - if Some(c) != s.chars().rev().next() { - panic!("character {:x}={} does not decode correctly", c as u32, c); - } - } -} - -#[test] -fn test_iterator_clone() { - let s = "ศไทย中华Việt Nam"; - let mut it = s.chars(); - it.next(); - assert!(it.clone().zip(it).all(|(x, y)| x == y)); -} - -#[test] -fn test_iterator_last() { - let s = "ศไทย中华Việt Nam"; - let mut it = s.chars(); - it.next(); - assert_eq!(it.last(), Some('m')); -} - -#[test] -fn test_chars_debug() { - let s = "ศไทย中华Việt Nam"; - let c = s.chars(); - assert_eq!( - format!("{:?}", c), - r#"Chars(['ศ', 'ไ', 'ท', 'ย', '中', '华', 'V', 'i', 'ệ', 't', ' ', 'N', 'a', 'm'])"# - ); -} - -#[test] -fn test_bytesator() { - let s = "ศไทย中华Việt Nam"; - let v = [ - 224, 184, 168, 224, 185, 132, 224, 184, 151, 224, 184, 162, 228, 184, 173, 229, 141, 142, - 86, 105, 225, 187, 135, 116, 32, 78, 97, 109, - ]; - let mut pos = 0; - - for b in s.bytes() { - assert_eq!(b, v[pos]); - pos += 1; - } -} - -#[test] -fn test_bytes_revator() { - let s = "ศไทย中华Việt Nam"; - let v = [ - 224, 184, 168, 224, 185, 132, 224, 184, 151, 224, 184, 162, 228, 184, 173, 229, 141, 142, - 86, 105, 225, 187, 135, 116, 32, 78, 97, 109, - ]; - let mut pos = v.len(); - - for b in s.bytes().rev() { - pos -= 1; - assert_eq!(b, v[pos]); - } -} - -#[test] -fn test_bytesator_nth() { - let s = "ศไทย中华Việt Nam"; - let v = [ - 224, 184, 168, 224, 185, 132, 224, 184, 151, 224, 184, 162, 228, 184, 173, 229, 141, 142, - 86, 105, 225, 187, 135, 116, 32, 78, 97, 109, - ]; - - let mut b = s.bytes(); - assert_eq!(b.nth(2).unwrap(), v[2]); - assert_eq!(b.nth(10).unwrap(), v[10]); - assert_eq!(b.nth(200), None); -} - -#[test] -fn test_bytesator_count() { - let s = "ศไทย中华Việt Nam"; - - let b = s.bytes(); - assert_eq!(b.count(), 28) -} - -#[test] -fn test_bytesator_last() { - let s = "ศไทย中华Việt Nam"; - - let b = s.bytes(); - assert_eq!(b.last().unwrap(), 109) -} - -#[test] -fn test_char_indicesator() { - let s = "ศไทย中华Việt Nam"; - let p = [0, 3, 6, 9, 12, 15, 18, 19, 20, 23, 24, 25, 26, 27]; - let v = ['ศ', 'ไ', 'ท', 'ย', '中', '华', 'V', 'i', 'ệ', 't', ' ', 'N', 'a', 'm']; - - let mut pos = 0; - let it = s.char_indices(); - - for c in it { - assert_eq!(c, (p[pos], v[pos])); - pos += 1; - } - assert_eq!(pos, v.len()); - assert_eq!(pos, p.len()); -} - -#[test] -fn test_char_indices_revator() { - let s = "ศไทย中华Việt Nam"; - let p = [27, 26, 25, 24, 23, 20, 19, 18, 15, 12, 9, 6, 3, 0]; - let v = ['m', 'a', 'N', ' ', 't', 'ệ', 'i', 'V', '华', '中', 'ย', 'ท', 'ไ', 'ศ']; - - let mut pos = 0; - let it = s.char_indices().rev(); - - for c in it { - assert_eq!(c, (p[pos], v[pos])); - pos += 1; - } - assert_eq!(pos, v.len()); - assert_eq!(pos, p.len()); -} - -#[test] -fn test_char_indices_last() { - let s = "ศไทย中华Việt Nam"; - let mut it = s.char_indices(); - it.next(); - assert_eq!(it.last(), Some((27, 'm'))); -} - -#[test] -fn test_splitn_char_iterator() { - let data = "\nMäry häd ä little lämb\nLittle lämb\n"; - - let split: Vec<&str> = data.splitn(4, ' ').collect(); - assert_eq!(split, ["\nMäry", "häd", "ä", "little lämb\nLittle lämb\n"]); - - let split: Vec<&str> = data.splitn(4, |c: char| c == ' ').collect(); - assert_eq!(split, ["\nMäry", "häd", "ä", "little lämb\nLittle lämb\n"]); - - // Unicode - let split: Vec<&str> = data.splitn(4, 'ä').collect(); - assert_eq!(split, ["\nM", "ry h", "d ", " little lämb\nLittle lämb\n"]); - - let split: Vec<&str> = data.splitn(4, |c: char| c == 'ä').collect(); - assert_eq!(split, ["\nM", "ry h", "d ", " little lämb\nLittle lämb\n"]); -} - -#[test] -fn test_split_char_iterator_no_trailing() { - let data = "\nMäry häd ä little lämb\nLittle lämb\n"; - - let split: Vec<&str> = data.split('\n').collect(); - assert_eq!(split, ["", "Märy häd ä little lämb", "Little lämb", ""]); - - let split: Vec<&str> = data.split_terminator('\n').collect(); - assert_eq!(split, ["", "Märy häd ä little lämb", "Little lämb"]); -} - -#[test] -fn test_split_char_iterator_inclusive() { - let data = "\nMäry häd ä little lämb\nLittle lämb\n"; - - let split: Vec<&str> = data.split_inclusive('\n').collect(); - assert_eq!(split, ["\n", "Märy häd ä little lämb\n", "Little lämb\n"]); - - let uppercase_separated = "SheePSharKTurtlECaT"; - let mut first_char = true; - let split: Vec<&str> = uppercase_separated - .split_inclusive(|c: char| { - let split = !first_char && c.is_uppercase(); - first_char = split; - split - }) - .collect(); - assert_eq!(split, ["SheeP", "SharK", "TurtlE", "CaT"]); -} - -#[test] -fn test_split_char_iterator_inclusive_rev() { - let data = "\nMäry häd ä little lämb\nLittle lämb\n"; - - let split: Vec<&str> = data.split_inclusive('\n').rev().collect(); - assert_eq!(split, ["Little lämb\n", "Märy häd ä little lämb\n", "\n"]); - - // Note that the predicate is stateful and thus dependent - // on the iteration order. - // (A different predicate is needed for reverse iterator vs normal iterator.) - // Not sure if anything can be done though. - let uppercase_separated = "SheePSharKTurtlECaT"; - let mut term_char = true; - let split: Vec<&str> = uppercase_separated - .split_inclusive(|c: char| { - let split = term_char && c.is_uppercase(); - term_char = c.is_uppercase(); - split - }) - .rev() - .collect(); - assert_eq!(split, ["CaT", "TurtlE", "SharK", "SheeP"]); -} - -#[test] -fn test_rsplit() { - let data = "\nMäry häd ä little lämb\nLittle lämb\n"; - - let split: Vec<&str> = data.rsplit(' ').collect(); - assert_eq!(split, ["lämb\n", "lämb\nLittle", "little", "ä", "häd", "\nMäry"]); - - let split: Vec<&str> = data.rsplit("lämb").collect(); - assert_eq!(split, ["\n", "\nLittle ", "\nMäry häd ä little "]); - - let split: Vec<&str> = data.rsplit(|c: char| c == 'ä').collect(); - assert_eq!(split, ["mb\n", "mb\nLittle l", " little l", "d ", "ry h", "\nM"]); -} - -#[test] -fn test_rsplitn() { - let data = "\nMäry häd ä little lämb\nLittle lämb\n"; - - let split: Vec<&str> = data.rsplitn(2, ' ').collect(); - assert_eq!(split, ["lämb\n", "\nMäry häd ä little lämb\nLittle"]); - - let split: Vec<&str> = data.rsplitn(2, "lämb").collect(); - assert_eq!(split, ["\n", "\nMäry häd ä little lämb\nLittle "]); - - let split: Vec<&str> = data.rsplitn(2, |c: char| c == 'ä').collect(); - assert_eq!(split, ["mb\n", "\nMäry häd ä little lämb\nLittle l"]); -} - -#[test] -fn test_split_whitespace() { - let data = "\n \tMäry häd\tä little lämb\nLittle lämb\n"; - let words: Vec<&str> = data.split_whitespace().collect(); - assert_eq!(words, ["Märy", "häd", "ä", "little", "lämb", "Little", "lämb"]) -} - -#[test] -fn test_lines() { - let data = "\nMäry häd ä little lämb\n\r\nLittle lämb\n"; - let lines: Vec<&str> = data.lines().collect(); - assert_eq!(lines, ["", "Märy häd ä little lämb", "", "Little lämb"]); - - let data = "\r\nMäry häd ä little lämb\n\nLittle lämb"; // no trailing \n - let lines: Vec<&str> = data.lines().collect(); - assert_eq!(lines, ["", "Märy häd ä little lämb", "", "Little lämb"]); -} - -#[test] -fn test_splitator() { - fn t(s: &str, sep: &str, u: &[&str]) { - let v: Vec<&str> = s.split(sep).collect(); - assert_eq!(v, u); - } - t("--1233345--", "12345", &["--1233345--"]); - t("abc::hello::there", "::", &["abc", "hello", "there"]); - t("::hello::there", "::", &["", "hello", "there"]); - t("hello::there::", "::", &["hello", "there", ""]); - t("::hello::there::", "::", &["", "hello", "there", ""]); - t("ประเทศไทย中华Việt Nam", "中华", &["ประเทศไทย", "Việt Nam"]); - t("zzXXXzzYYYzz", "zz", &["", "XXX", "YYY", ""]); - t("zzXXXzYYYz", "XXX", &["zz", "zYYYz"]); - t(".XXX.YYY.", ".", &["", "XXX", "YYY", ""]); - t("", ".", &[""]); - t("zz", "zz", &["", ""]); - t("ok", "z", &["ok"]); - t("zzz", "zz", &["", "z"]); - t("zzzzz", "zz", &["", "", "z"]); -} - -#[test] -fn test_str_default() { - use std::default::Default; - - fn t<S: Default + AsRef<str>>() { - let s: S = Default::default(); - assert_eq!(s.as_ref(), ""); - } - - t::<&str>(); - t::<String>(); - t::<&mut str>(); -} - -#[test] -fn test_str_container() { - fn sum_len(v: &[&str]) -> usize { - v.iter().map(|x| x.len()).sum() - } - - let s = "01234"; - assert_eq!(5, sum_len(&["012", "", "34"])); - assert_eq!(5, sum_len(&["01", "2", "34", ""])); - assert_eq!(5, sum_len(&[s])); -} - -#[test] -fn test_str_from_utf8() { - let xs = b"hello"; - assert_eq!(from_utf8(xs), Ok("hello")); - - let xs = "ศไทย中华Việt Nam".as_bytes(); - assert_eq!(from_utf8(xs), Ok("ศไทย中华Việt Nam")); - - let xs = b"hello\xFF"; - assert!(from_utf8(xs).is_err()); -} - -#[test] -fn test_pattern_deref_forward() { - let data = "aabcdaa"; - assert!(data.contains("bcd")); - assert!(data.contains(&"bcd")); - assert!(data.contains(&"bcd".to_string())); -} - -#[test] -fn test_empty_match_indices() { - let data = "aä中!"; - let vec: Vec<_> = data.match_indices("").collect(); - assert_eq!(vec, [(0, ""), (1, ""), (3, ""), (6, ""), (7, "")]); -} - -#[test] -fn test_bool_from_str() { - assert_eq!("true".parse().ok(), Some(true)); - assert_eq!("false".parse().ok(), Some(false)); - assert_eq!("not even a boolean".parse::<bool>().ok(), None); -} - -fn check_contains_all_substrings(s: &str) { - assert!(s.contains("")); - for i in 0..s.len() { - for j in i + 1..=s.len() { - assert!(s.contains(&s[i..j])); - } - } -} - -#[test] -#[cfg_attr(miri, ignore)] // Miri is too slow -fn strslice_issue_16589() { - assert!("bananas".contains("nana")); - - // prior to the fix for #16589, x.contains("abcdabcd") returned false - // test all substrings for good measure - check_contains_all_substrings("012345678901234567890123456789bcdabcdabcd"); -} - -#[test] -fn strslice_issue_16878() { - assert!(!"1234567ah012345678901ah".contains("hah")); - assert!(!"00abc01234567890123456789abc".contains("bcabc")); -} - -#[test] -#[cfg_attr(miri, ignore)] // Miri is too slow -fn test_strslice_contains() { - let x = "There are moments, Jeeves, when one asks oneself, 'Do trousers matter?'"; - check_contains_all_substrings(x); -} - -#[test] -fn test_rsplitn_char_iterator() { - let data = "\nMäry häd ä little lämb\nLittle lämb\n"; - - let mut split: Vec<&str> = data.rsplitn(4, ' ').collect(); - split.reverse(); - assert_eq!(split, ["\nMäry häd ä", "little", "lämb\nLittle", "lämb\n"]); - - let mut split: Vec<&str> = data.rsplitn(4, |c: char| c == ' ').collect(); - split.reverse(); - assert_eq!(split, ["\nMäry häd ä", "little", "lämb\nLittle", "lämb\n"]); - - // Unicode - let mut split: Vec<&str> = data.rsplitn(4, 'ä').collect(); - split.reverse(); - assert_eq!(split, ["\nMäry häd ", " little l", "mb\nLittle l", "mb\n"]); - - let mut split: Vec<&str> = data.rsplitn(4, |c: char| c == 'ä').collect(); - split.reverse(); - assert_eq!(split, ["\nMäry häd ", " little l", "mb\nLittle l", "mb\n"]); -} - -#[test] -fn test_split_char_iterator() { - let data = "\nMäry häd ä little lämb\nLittle lämb\n"; - - let split: Vec<&str> = data.split(' ').collect(); - assert_eq!(split, ["\nMäry", "häd", "ä", "little", "lämb\nLittle", "lämb\n"]); - - let mut rsplit: Vec<&str> = data.split(' ').rev().collect(); - rsplit.reverse(); - assert_eq!(rsplit, ["\nMäry", "häd", "ä", "little", "lämb\nLittle", "lämb\n"]); - - let split: Vec<&str> = data.split(|c: char| c == ' ').collect(); - assert_eq!(split, ["\nMäry", "häd", "ä", "little", "lämb\nLittle", "lämb\n"]); - - let mut rsplit: Vec<&str> = data.split(|c: char| c == ' ').rev().collect(); - rsplit.reverse(); - assert_eq!(rsplit, ["\nMäry", "häd", "ä", "little", "lämb\nLittle", "lämb\n"]); - - // Unicode - let split: Vec<&str> = data.split('ä').collect(); - assert_eq!(split, ["\nM", "ry h", "d ", " little l", "mb\nLittle l", "mb\n"]); - - let mut rsplit: Vec<&str> = data.split('ä').rev().collect(); - rsplit.reverse(); - assert_eq!(rsplit, ["\nM", "ry h", "d ", " little l", "mb\nLittle l", "mb\n"]); - - let split: Vec<&str> = data.split(|c: char| c == 'ä').collect(); - assert_eq!(split, ["\nM", "ry h", "d ", " little l", "mb\nLittle l", "mb\n"]); - - let mut rsplit: Vec<&str> = data.split(|c: char| c == 'ä').rev().collect(); - rsplit.reverse(); - assert_eq!(rsplit, ["\nM", "ry h", "d ", " little l", "mb\nLittle l", "mb\n"]); -} - -#[test] -fn test_rev_split_char_iterator_no_trailing() { - let data = "\nMäry häd ä little lämb\nLittle lämb\n"; - - let mut split: Vec<&str> = data.split('\n').rev().collect(); - split.reverse(); - assert_eq!(split, ["", "Märy häd ä little lämb", "Little lämb", ""]); - - let mut split: Vec<&str> = data.split_terminator('\n').rev().collect(); - split.reverse(); - assert_eq!(split, ["", "Märy häd ä little lämb", "Little lämb"]); -} - -#[test] -fn test_utf16_code_units() { - assert_eq!("é\u{1F4A9}".encode_utf16().collect::<Vec<u16>>(), [0xE9, 0xD83D, 0xDCA9]) -} - -#[test] -fn starts_with_in_unicode() { - assert!(!"├── Cargo.toml".starts_with("# ")); -} - -#[test] -fn starts_short_long() { - assert!(!"".starts_with("##")); - assert!(!"##".starts_with("####")); - assert!("####".starts_with("##")); - assert!(!"##ä".starts_with("####")); - assert!("####ä".starts_with("##")); - assert!(!"##".starts_with("####ä")); - assert!("##ä##".starts_with("##ä")); - - assert!("".starts_with("")); - assert!("ä".starts_with("")); - assert!("#ä".starts_with("")); - assert!("##ä".starts_with("")); - assert!("ä###".starts_with("")); - assert!("#ä##".starts_with("")); - assert!("##ä#".starts_with("")); -} - -#[test] -fn contains_weird_cases() { - assert!("* \t".contains(' ')); - assert!(!"* \t".contains('?')); - assert!(!"* \t".contains('\u{1F4A9}')); -} - -#[test] -fn trim_ws() { - assert_eq!(" \t a \t ".trim_start_matches(|c: char| c.is_whitespace()), "a \t "); - assert_eq!(" \t a \t ".trim_end_matches(|c: char| c.is_whitespace()), " \t a"); - assert_eq!(" \t a \t ".trim_start_matches(|c: char| c.is_whitespace()), "a \t "); - assert_eq!(" \t a \t ".trim_end_matches(|c: char| c.is_whitespace()), " \t a"); - assert_eq!(" \t a \t ".trim_matches(|c: char| c.is_whitespace()), "a"); - assert_eq!(" \t \t ".trim_start_matches(|c: char| c.is_whitespace()), ""); - assert_eq!(" \t \t ".trim_end_matches(|c: char| c.is_whitespace()), ""); - assert_eq!(" \t \t ".trim_start_matches(|c: char| c.is_whitespace()), ""); - assert_eq!(" \t \t ".trim_end_matches(|c: char| c.is_whitespace()), ""); - assert_eq!(" \t \t ".trim_matches(|c: char| c.is_whitespace()), ""); -} - -#[test] -fn to_lowercase() { - assert_eq!("".to_lowercase(), ""); - assert_eq!("AÉDžaé ".to_lowercase(), "aédžaé "); - - // https://github.com/rust-lang/rust/issues/26035 - assert_eq!("ΑΣ".to_lowercase(), "ας"); - assert_eq!("Α'Σ".to_lowercase(), "α'ς"); - assert_eq!("Α''Σ".to_lowercase(), "α''ς"); - - assert_eq!("ΑΣ Α".to_lowercase(), "ας α"); - assert_eq!("Α'Σ Α".to_lowercase(), "α'ς α"); - assert_eq!("Α''Σ Α".to_lowercase(), "α''ς α"); - - assert_eq!("ΑΣ' Α".to_lowercase(), "ας' α"); - assert_eq!("ΑΣ'' Α".to_lowercase(), "ας'' α"); - - assert_eq!("Α'Σ' Α".to_lowercase(), "α'ς' α"); - assert_eq!("Α''Σ'' Α".to_lowercase(), "α''ς'' α"); - - assert_eq!("Α Σ".to_lowercase(), "α σ"); - assert_eq!("Α 'Σ".to_lowercase(), "α 'σ"); - assert_eq!("Α ''Σ".to_lowercase(), "α ''σ"); - - assert_eq!("Σ".to_lowercase(), "σ"); - assert_eq!("'Σ".to_lowercase(), "'σ"); - assert_eq!("''Σ".to_lowercase(), "''σ"); - - assert_eq!("ΑΣΑ".to_lowercase(), "ασα"); - assert_eq!("ΑΣ'Α".to_lowercase(), "ασ'α"); - assert_eq!("ΑΣ''Α".to_lowercase(), "ασ''α"); -} - -#[test] -fn to_uppercase() { - assert_eq!("".to_uppercase(), ""); - assert_eq!("aéDžßfiᾀ".to_uppercase(), "AÉDŽSSFIἈΙ"); -} - -#[test] -fn test_into_string() { - // The only way to acquire a Box<str> in the first place is through a String, so just - // test that we can round-trip between Box<str> and String. - let string = String::from("Some text goes here"); - assert_eq!(string.clone().into_boxed_str().into_string(), string); -} - -#[test] -fn test_box_slice_clone() { - let data = String::from("hello HELLO hello HELLO yes YES 5 中ä华!!!"); - let data2 = data.clone().into_boxed_str().clone().into_string(); - - assert_eq!(data, data2); -} - -#[test] -fn test_cow_from() { - let borrowed = "borrowed"; - let owned = String::from("owned"); - match (Cow::from(owned.clone()), Cow::from(borrowed)) { - (Cow::Owned(o), Cow::Borrowed(b)) => assert!(o == owned && b == borrowed), - _ => panic!("invalid `Cow::from`"), - } -} - -#[test] -fn test_repeat() { - assert_eq!("".repeat(3), ""); - assert_eq!("abc".repeat(0), ""); - assert_eq!("α".repeat(3), "ααα"); -} - -mod pattern { - use std::str::pattern::SearchStep::{self, Done, Match, Reject}; - use std::str::pattern::{Pattern, ReverseSearcher, Searcher}; - - macro_rules! make_test { - ($name:ident, $p:expr, $h:expr, [$($e:expr,)*]) => { - #[allow(unused_imports)] - mod $name { - use std::str::pattern::SearchStep::{Match, Reject}; - use super::{cmp_search_to_vec}; - #[test] - fn fwd() { - cmp_search_to_vec(false, $p, $h, vec![$($e),*]); - } - #[test] - fn bwd() { - cmp_search_to_vec(true, $p, $h, vec![$($e),*]); - } - } - } - } - - fn cmp_search_to_vec<'a>( - rev: bool, - pat: impl Pattern<'a, Searcher: ReverseSearcher<'a>>, - haystack: &'a str, - right: Vec<SearchStep>, - ) { - let mut searcher = pat.into_searcher(haystack); - let mut v = vec![]; - loop { - match if !rev { searcher.next() } else { searcher.next_back() } { - Match(a, b) => v.push(Match(a, b)), - Reject(a, b) => v.push(Reject(a, b)), - Done => break, - } - } - if rev { - v.reverse(); - } - - let mut first_index = 0; - let mut err = None; - - for (i, e) in right.iter().enumerate() { - match *e { - Match(a, b) | Reject(a, b) if a <= b && a == first_index => { - first_index = b; - } - _ => { - err = Some(i); - break; - } - } - } - - if let Some(err) = err { - panic!("Input skipped range at {}", err); - } - - if first_index != haystack.len() { - panic!("Did not cover whole input"); - } - - assert_eq!(v, right); - } - - make_test!( - str_searcher_ascii_haystack, - "bb", - "abbcbbd", - [Reject(0, 1), Match(1, 3), Reject(3, 4), Match(4, 6), Reject(6, 7),] - ); - make_test!( - str_searcher_ascii_haystack_seq, - "bb", - "abbcbbbbd", - [Reject(0, 1), Match(1, 3), Reject(3, 4), Match(4, 6), Match(6, 8), Reject(8, 9),] - ); - make_test!( - str_searcher_empty_needle_ascii_haystack, - "", - "abbcbbd", - [ - Match(0, 0), - Reject(0, 1), - Match(1, 1), - Reject(1, 2), - Match(2, 2), - Reject(2, 3), - Match(3, 3), - Reject(3, 4), - Match(4, 4), - Reject(4, 5), - Match(5, 5), - Reject(5, 6), - Match(6, 6), - Reject(6, 7), - Match(7, 7), - ] - ); - make_test!( - str_searcher_multibyte_haystack, - " ", - "├──", - [Reject(0, 3), Reject(3, 6), Reject(6, 9),] - ); - make_test!( - str_searcher_empty_needle_multibyte_haystack, - "", - "├──", - [ - Match(0, 0), - Reject(0, 3), - Match(3, 3), - Reject(3, 6), - Match(6, 6), - Reject(6, 9), - Match(9, 9), - ] - ); - make_test!(str_searcher_empty_needle_empty_haystack, "", "", [Match(0, 0),]); - make_test!(str_searcher_nonempty_needle_empty_haystack, "├", "", []); - make_test!( - char_searcher_ascii_haystack, - 'b', - "abbcbbd", - [ - Reject(0, 1), - Match(1, 2), - Match(2, 3), - Reject(3, 4), - Match(4, 5), - Match(5, 6), - Reject(6, 7), - ] - ); - make_test!( - char_searcher_multibyte_haystack, - ' ', - "├──", - [Reject(0, 3), Reject(3, 6), Reject(6, 9),] - ); - make_test!( - char_searcher_short_haystack, - '\u{1F4A9}', - "* \t", - [Reject(0, 1), Reject(1, 2), Reject(2, 3),] - ); -} - -macro_rules! generate_iterator_test { - { - $name:ident { - $( - ($($arg:expr),*) -> [$($t:tt)*]; - )* - } - with $fwd:expr, $bwd:expr; - } => { - #[test] - fn $name() { - $( - { - let res = vec![$($t)*]; - - let fwd_vec: Vec<_> = ($fwd)($($arg),*).collect(); - assert_eq!(fwd_vec, res); - - let mut bwd_vec: Vec<_> = ($bwd)($($arg),*).collect(); - bwd_vec.reverse(); - assert_eq!(bwd_vec, res); - } - )* - } - }; - { - $name:ident { - $( - ($($arg:expr),*) -> [$($t:tt)*]; - )* - } - with $fwd:expr; - } => { - #[test] - fn $name() { - $( - { - let res = vec![$($t)*]; - - let fwd_vec: Vec<_> = ($fwd)($($arg),*).collect(); - assert_eq!(fwd_vec, res); - } - )* - } - } -} - -generate_iterator_test! { - double_ended_split { - ("foo.bar.baz", '.') -> ["foo", "bar", "baz"]; - ("foo::bar::baz", "::") -> ["foo", "bar", "baz"]; - } - with str::split, str::rsplit; -} - -generate_iterator_test! { - double_ended_split_terminator { - ("foo;bar;baz;", ';') -> ["foo", "bar", "baz"]; - } - with str::split_terminator, str::rsplit_terminator; -} - -generate_iterator_test! { - double_ended_matches { - ("a1b2c3", char::is_numeric) -> ["1", "2", "3"]; - } - with str::matches, str::rmatches; -} - -generate_iterator_test! { - double_ended_match_indices { - ("a1b2c3", char::is_numeric) -> [(1, "1"), (3, "2"), (5, "3")]; - } - with str::match_indices, str::rmatch_indices; -} - -generate_iterator_test! { - not_double_ended_splitn { - ("foo::bar::baz", 2, "::") -> ["foo", "bar::baz"]; - } - with str::splitn; -} - -generate_iterator_test! { - not_double_ended_rsplitn { - ("foo::bar::baz", 2, "::") -> ["baz", "foo::bar"]; - } - with str::rsplitn; -} - -#[test] -fn different_str_pattern_forwarding_lifetimes() { - use std::str::pattern::Pattern; - - fn foo<'a, P>(p: P) - where - for<'b> &'b P: Pattern<'a>, - { - for _ in 0..3 { - "asdf".find(&p); - } - } - - foo::<&str>("x"); -} diff --git a/src/liballoc/tests/string.rs b/src/liballoc/tests/string.rs deleted file mode 100644 index d38655af78c..00000000000 --- a/src/liballoc/tests/string.rs +++ /dev/null @@ -1,723 +0,0 @@ -use std::borrow::Cow; -use std::collections::TryReserveError::*; -use std::mem::size_of; - -pub trait IntoCow<'a, B: ?Sized> -where - B: ToOwned, -{ - fn into_cow(self) -> Cow<'a, B>; -} - -impl<'a> IntoCow<'a, str> for String { - fn into_cow(self) -> Cow<'a, str> { - Cow::Owned(self) - } -} - -impl<'a> IntoCow<'a, str> for &'a str { - fn into_cow(self) -> Cow<'a, str> { - Cow::Borrowed(self) - } -} - -#[test] -fn test_from_str() { - let owned: Option<std::string::String> = "string".parse().ok(); - assert_eq!(owned.as_ref().map(|s| &**s), Some("string")); -} - -#[test] -fn test_from_cow_str() { - assert_eq!(String::from(Cow::Borrowed("string")), "string"); - assert_eq!(String::from(Cow::Owned(String::from("string"))), "string"); -} - -#[test] -fn test_unsized_to_string() { - let s: &str = "abc"; - let _: String = (*s).to_string(); -} - -#[test] -fn test_from_utf8() { - let xs = b"hello".to_vec(); - assert_eq!(String::from_utf8(xs).unwrap(), String::from("hello")); - - let xs = "ศไทย中华Việt Nam".as_bytes().to_vec(); - assert_eq!(String::from_utf8(xs).unwrap(), String::from("ศไทย中华Việt Nam")); - - let xs = b"hello\xFF".to_vec(); - let err = String::from_utf8(xs).unwrap_err(); - assert_eq!(err.as_bytes(), b"hello\xff"); - let err_clone = err.clone(); - assert_eq!(err, err_clone); - assert_eq!(err.into_bytes(), b"hello\xff".to_vec()); - assert_eq!(err_clone.utf8_error().valid_up_to(), 5); -} - -#[test] -fn test_from_utf8_lossy() { - let xs = b"hello"; - let ys: Cow<'_, str> = "hello".into_cow(); - assert_eq!(String::from_utf8_lossy(xs), ys); - - let xs = "ศไทย中华Việt Nam".as_bytes(); - let ys: Cow<'_, str> = "ศไทย中华Việt Nam".into_cow(); - assert_eq!(String::from_utf8_lossy(xs), ys); - - let xs = b"Hello\xC2 There\xFF Goodbye"; - assert_eq!( - String::from_utf8_lossy(xs), - String::from("Hello\u{FFFD} There\u{FFFD} Goodbye").into_cow() - ); - - let xs = b"Hello\xC0\x80 There\xE6\x83 Goodbye"; - assert_eq!( - String::from_utf8_lossy(xs), - String::from("Hello\u{FFFD}\u{FFFD} There\u{FFFD} Goodbye").into_cow() - ); - - let xs = b"\xF5foo\xF5\x80bar"; - assert_eq!( - String::from_utf8_lossy(xs), - String::from("\u{FFFD}foo\u{FFFD}\u{FFFD}bar").into_cow() - ); - - let xs = b"\xF1foo\xF1\x80bar\xF1\x80\x80baz"; - assert_eq!( - String::from_utf8_lossy(xs), - String::from("\u{FFFD}foo\u{FFFD}bar\u{FFFD}baz").into_cow() - ); - - let xs = b"\xF4foo\xF4\x80bar\xF4\xBFbaz"; - assert_eq!( - String::from_utf8_lossy(xs), - String::from("\u{FFFD}foo\u{FFFD}bar\u{FFFD}\u{FFFD}baz").into_cow() - ); - - let xs = b"\xF0\x80\x80\x80foo\xF0\x90\x80\x80bar"; - assert_eq!( - String::from_utf8_lossy(xs), - String::from("\u{FFFD}\u{FFFD}\u{FFFD}\u{FFFD}foo\u{10000}bar").into_cow() - ); - - // surrogates - let xs = b"\xED\xA0\x80foo\xED\xBF\xBFbar"; - assert_eq!( - String::from_utf8_lossy(xs), - String::from("\u{FFFD}\u{FFFD}\u{FFFD}foo\u{FFFD}\u{FFFD}\u{FFFD}bar").into_cow() - ); -} - -#[test] -fn test_from_utf16() { - let pairs = [ - ( - String::from("𐍅𐌿𐌻𐍆𐌹𐌻𐌰\n"), - vec![ - 0xd800, 0xdf45, 0xd800, 0xdf3f, 0xd800, 0xdf3b, 0xd800, 0xdf46, 0xd800, 0xdf39, - 0xd800, 0xdf3b, 0xd800, 0xdf30, 0x000a, - ], - ), - ( - String::from("𐐒𐑉𐐮𐑀𐐲𐑋 𐐏𐐲𐑍\n"), - vec![ - 0xd801, 0xdc12, 0xd801, 0xdc49, 0xd801, 0xdc2e, 0xd801, 0xdc40, 0xd801, 0xdc32, - 0xd801, 0xdc4b, 0x0020, 0xd801, 0xdc0f, 0xd801, 0xdc32, 0xd801, 0xdc4d, 0x000a, - ], - ), - ( - String::from("𐌀𐌖𐌋𐌄𐌑𐌉·𐌌𐌄𐌕𐌄𐌋𐌉𐌑\n"), - vec![ - 0xd800, 0xdf00, 0xd800, 0xdf16, 0xd800, 0xdf0b, 0xd800, 0xdf04, 0xd800, 0xdf11, - 0xd800, 0xdf09, 0x00b7, 0xd800, 0xdf0c, 0xd800, 0xdf04, 0xd800, 0xdf15, 0xd800, - 0xdf04, 0xd800, 0xdf0b, 0xd800, 0xdf09, 0xd800, 0xdf11, 0x000a, - ], - ), - ( - String::from("𐒋𐒘𐒈𐒑𐒛𐒒 𐒕𐒓 𐒈𐒚𐒍 𐒏𐒜𐒒𐒖𐒆 𐒕𐒆\n"), - vec![ - 0xd801, 0xdc8b, 0xd801, 0xdc98, 0xd801, 0xdc88, 0xd801, 0xdc91, 0xd801, 0xdc9b, - 0xd801, 0xdc92, 0x0020, 0xd801, 0xdc95, 0xd801, 0xdc93, 0x0020, 0xd801, 0xdc88, - 0xd801, 0xdc9a, 0xd801, 0xdc8d, 0x0020, 0xd801, 0xdc8f, 0xd801, 0xdc9c, 0xd801, - 0xdc92, 0xd801, 0xdc96, 0xd801, 0xdc86, 0x0020, 0xd801, 0xdc95, 0xd801, 0xdc86, - 0x000a, - ], - ), - // Issue #12318, even-numbered non-BMP planes - (String::from("\u{20000}"), vec![0xD840, 0xDC00]), - ]; - - for p in &pairs { - let (s, u) = (*p).clone(); - let s_as_utf16 = s.encode_utf16().collect::<Vec<u16>>(); - let u_as_string = String::from_utf16(&u).unwrap(); - - assert!(core::char::decode_utf16(u.iter().cloned()).all(|r| r.is_ok())); - assert_eq!(s_as_utf16, u); - - assert_eq!(u_as_string, s); - assert_eq!(String::from_utf16_lossy(&u), s); - - assert_eq!(String::from_utf16(&s_as_utf16).unwrap(), s); - assert_eq!(u_as_string.encode_utf16().collect::<Vec<u16>>(), u); - } -} - -#[test] -fn test_utf16_invalid() { - // completely positive cases tested above. - // lead + eof - assert!(String::from_utf16(&[0xD800]).is_err()); - // lead + lead - assert!(String::from_utf16(&[0xD800, 0xD800]).is_err()); - - // isolated trail - assert!(String::from_utf16(&[0x0061, 0xDC00]).is_err()); - - // general - assert!(String::from_utf16(&[0xD800, 0xd801, 0xdc8b, 0xD800]).is_err()); -} - -#[test] -fn test_from_utf16_lossy() { - // completely positive cases tested above. - // lead + eof - assert_eq!(String::from_utf16_lossy(&[0xD800]), String::from("\u{FFFD}")); - // lead + lead - assert_eq!(String::from_utf16_lossy(&[0xD800, 0xD800]), String::from("\u{FFFD}\u{FFFD}")); - - // isolated trail - assert_eq!(String::from_utf16_lossy(&[0x0061, 0xDC00]), String::from("a\u{FFFD}")); - - // general - assert_eq!( - String::from_utf16_lossy(&[0xD800, 0xd801, 0xdc8b, 0xD800]), - String::from("\u{FFFD}𐒋\u{FFFD}") - ); -} - -#[test] -fn test_push_bytes() { - let mut s = String::from("ABC"); - unsafe { - let mv = s.as_mut_vec(); - mv.extend_from_slice(&[b'D']); - } - assert_eq!(s, "ABCD"); -} - -#[test] -fn test_push_str() { - let mut s = String::new(); - s.push_str(""); - assert_eq!(&s[0..], ""); - s.push_str("abc"); - assert_eq!(&s[0..], "abc"); - s.push_str("ประเทศไทย中华Việt Nam"); - assert_eq!(&s[0..], "abcประเทศไทย中华Việt Nam"); -} - -#[test] -fn test_add_assign() { - let mut s = String::new(); - s += ""; - assert_eq!(s.as_str(), ""); - s += "abc"; - assert_eq!(s.as_str(), "abc"); - s += "ประเทศไทย中华Việt Nam"; - assert_eq!(s.as_str(), "abcประเทศไทย中华Việt Nam"); -} - -#[test] -fn test_push() { - let mut data = String::from("ประเทศไทย中"); - data.push('华'); - data.push('b'); // 1 byte - data.push('¢'); // 2 byte - data.push('€'); // 3 byte - data.push('𤭢'); // 4 byte - assert_eq!(data, "ประเทศไทย中华b¢€𤭢"); -} - -#[test] -fn test_pop() { - let mut data = String::from("ประเทศไทย中华b¢€𤭢"); - assert_eq!(data.pop().unwrap(), '𤭢'); // 4 bytes - assert_eq!(data.pop().unwrap(), '€'); // 3 bytes - assert_eq!(data.pop().unwrap(), '¢'); // 2 bytes - assert_eq!(data.pop().unwrap(), 'b'); // 1 bytes - assert_eq!(data.pop().unwrap(), '华'); - assert_eq!(data, "ประเทศไทย中"); -} - -#[test] -fn test_split_off_empty() { - let orig = "Hello, world!"; - let mut split = String::from(orig); - let empty: String = split.split_off(orig.len()); - assert!(empty.is_empty()); -} - -#[test] -#[should_panic] -fn test_split_off_past_end() { - let orig = "Hello, world!"; - let mut split = String::from(orig); - let _ = split.split_off(orig.len() + 1); -} - -#[test] -#[should_panic] -fn test_split_off_mid_char() { - let mut orig = String::from("山"); - let _ = orig.split_off(1); -} - -#[test] -fn test_split_off_ascii() { - let mut ab = String::from("ABCD"); - let cd = ab.split_off(2); - assert_eq!(ab, "AB"); - assert_eq!(cd, "CD"); -} - -#[test] -fn test_split_off_unicode() { - let mut nihon = String::from("日本語"); - let go = nihon.split_off("日本".len()); - assert_eq!(nihon, "日本"); - assert_eq!(go, "語"); -} - -#[test] -fn test_str_truncate() { - let mut s = String::from("12345"); - s.truncate(5); - assert_eq!(s, "12345"); - s.truncate(3); - assert_eq!(s, "123"); - s.truncate(0); - assert_eq!(s, ""); - - let mut s = String::from("12345"); - let p = s.as_ptr(); - s.truncate(3); - s.push_str("6"); - let p_ = s.as_ptr(); - assert_eq!(p_, p); -} - -#[test] -fn test_str_truncate_invalid_len() { - let mut s = String::from("12345"); - s.truncate(6); - assert_eq!(s, "12345"); -} - -#[test] -#[should_panic] -fn test_str_truncate_split_codepoint() { - let mut s = String::from("\u{FC}"); // ü - s.truncate(1); -} - -#[test] -fn test_str_clear() { - let mut s = String::from("12345"); - s.clear(); - assert_eq!(s.len(), 0); - assert_eq!(s, ""); -} - -#[test] -fn test_str_add() { - let a = String::from("12345"); - let b = a + "2"; - let b = b + "2"; - assert_eq!(b.len(), 7); - assert_eq!(b, "1234522"); -} - -#[test] -fn remove() { - let mut s = "ศไทย中华Việt Nam; foobar".to_string(); - assert_eq!(s.remove(0), 'ศ'); - assert_eq!(s.len(), 33); - assert_eq!(s, "ไทย中华Việt Nam; foobar"); - assert_eq!(s.remove(17), 'ệ'); - assert_eq!(s, "ไทย中华Vit Nam; foobar"); -} - -#[test] -#[should_panic] -fn remove_bad() { - "ศ".to_string().remove(1); -} - -#[test] -fn test_retain() { - let mut s = String::from("α_β_γ"); - - s.retain(|_| true); - assert_eq!(s, "α_β_γ"); - - s.retain(|c| c != '_'); - assert_eq!(s, "αβγ"); - - s.retain(|c| c != 'β'); - assert_eq!(s, "αγ"); - - s.retain(|c| c == 'α'); - assert_eq!(s, "α"); - - s.retain(|_| false); - assert_eq!(s, ""); -} - -#[test] -fn insert() { - let mut s = "foobar".to_string(); - s.insert(0, 'ệ'); - assert_eq!(s, "ệfoobar"); - s.insert(6, 'ย'); - assert_eq!(s, "ệfooยbar"); -} - -#[test] -#[should_panic] -fn insert_bad1() { - "".to_string().insert(1, 't'); -} -#[test] -#[should_panic] -fn insert_bad2() { - "ệ".to_string().insert(1, 't'); -} - -#[test] -fn test_slicing() { - let s = "foobar".to_string(); - assert_eq!("foobar", &s[..]); - assert_eq!("foo", &s[..3]); - assert_eq!("bar", &s[3..]); - assert_eq!("oob", &s[1..4]); -} - -#[test] -fn test_simple_types() { - assert_eq!(1.to_string(), "1"); - assert_eq!((-1).to_string(), "-1"); - assert_eq!(200.to_string(), "200"); - assert_eq!(2.to_string(), "2"); - assert_eq!(true.to_string(), "true"); - assert_eq!(false.to_string(), "false"); - assert_eq!(("hi".to_string()).to_string(), "hi"); -} - -#[test] -fn test_vectors() { - let x: Vec<i32> = vec![]; - assert_eq!(format!("{:?}", x), "[]"); - assert_eq!(format!("{:?}", vec![1]), "[1]"); - assert_eq!(format!("{:?}", vec![1, 2, 3]), "[1, 2, 3]"); - assert!(format!("{:?}", vec![vec![], vec![1], vec![1, 1]]) == "[[], [1], [1, 1]]"); -} - -#[test] -fn test_from_iterator() { - let s = "ศไทย中华Việt Nam".to_string(); - let t = "ศไทย中华"; - let u = "Việt Nam"; - - let a: String = s.chars().collect(); - assert_eq!(s, a); - - let mut b = t.to_string(); - b.extend(u.chars()); - assert_eq!(s, b); - - let c: String = vec![t, u].into_iter().collect(); - assert_eq!(s, c); - - let mut d = t.to_string(); - d.extend(vec![u]); - assert_eq!(s, d); -} - -#[test] -fn test_drain() { - let mut s = String::from("αβγ"); - assert_eq!(s.drain(2..4).collect::<String>(), "β"); - assert_eq!(s, "αγ"); - - let mut t = String::from("abcd"); - t.drain(..0); - assert_eq!(t, "abcd"); - t.drain(..1); - assert_eq!(t, "bcd"); - t.drain(3..); - assert_eq!(t, "bcd"); - t.drain(..); - assert_eq!(t, ""); -} - -#[test] -fn test_replace_range() { - let mut s = "Hello, world!".to_owned(); - s.replace_range(7..12, "世界"); - assert_eq!(s, "Hello, 世界!"); -} - -#[test] -#[should_panic] -fn test_replace_range_char_boundary() { - let mut s = "Hello, 世界!".to_owned(); - s.replace_range(..8, ""); -} - -#[test] -fn test_replace_range_inclusive_range() { - let mut v = String::from("12345"); - v.replace_range(2..=3, "789"); - assert_eq!(v, "127895"); - v.replace_range(1..=2, "A"); - assert_eq!(v, "1A895"); -} - -#[test] -#[should_panic] -fn test_replace_range_out_of_bounds() { - let mut s = String::from("12345"); - s.replace_range(5..6, "789"); -} - -#[test] -#[should_panic] -fn test_replace_range_inclusive_out_of_bounds() { - let mut s = String::from("12345"); - s.replace_range(5..=5, "789"); -} - -#[test] -fn test_replace_range_empty() { - let mut s = String::from("12345"); - s.replace_range(1..2, ""); - assert_eq!(s, "1345"); -} - -#[test] -fn test_replace_range_unbounded() { - let mut s = String::from("12345"); - s.replace_range(.., ""); - assert_eq!(s, ""); -} - -#[test] -fn test_extend_ref() { - let mut a = "foo".to_string(); - a.extend(&['b', 'a', 'r']); - - assert_eq!(&a, "foobar"); -} - -#[test] -fn test_into_boxed_str() { - let xs = String::from("hello my name is bob"); - let ys = xs.into_boxed_str(); - assert_eq!(&*ys, "hello my name is bob"); -} - -#[test] -fn test_reserve_exact() { - // This is all the same as test_reserve - - let mut s = String::new(); - assert_eq!(s.capacity(), 0); - - s.reserve_exact(2); - assert!(s.capacity() >= 2); - - for _i in 0..16 { - s.push('0'); - } - - assert!(s.capacity() >= 16); - s.reserve_exact(16); - assert!(s.capacity() >= 32); - - s.push('0'); - - s.reserve_exact(16); - assert!(s.capacity() >= 33) -} - -#[test] -#[cfg_attr(miri, ignore)] // Miri does not support signalling OOM -#[cfg_attr(target_os = "android", ignore)] // Android used in CI has a broken dlmalloc -fn test_try_reserve() { - // These are the interesting cases: - // * exactly isize::MAX should never trigger a CapacityOverflow (can be OOM) - // * > isize::MAX should always fail - // * On 16/32-bit should CapacityOverflow - // * On 64-bit should OOM - // * overflow may trigger when adding `len` to `cap` (in number of elements) - // * overflow may trigger when multiplying `new_cap` by size_of::<T> (to get bytes) - - const MAX_CAP: usize = isize::MAX as usize; - const MAX_USIZE: usize = usize::MAX; - - // On 16/32-bit, we check that allocations don't exceed isize::MAX, - // on 64-bit, we assume the OS will give an OOM for such a ridiculous size. - // Any platform that succeeds for these requests is technically broken with - // ptr::offset because LLVM is the worst. - let guards_against_isize = size_of::<usize>() < 8; - - { - // Note: basic stuff is checked by test_reserve - let mut empty_string: String = String::new(); - - // Check isize::MAX doesn't count as an overflow - if let Err(CapacityOverflow) = empty_string.try_reserve(MAX_CAP) { - panic!("isize::MAX shouldn't trigger an overflow!"); - } - // Play it again, frank! (just to be sure) - if let Err(CapacityOverflow) = empty_string.try_reserve(MAX_CAP) { - panic!("isize::MAX shouldn't trigger an overflow!"); - } - - if guards_against_isize { - // Check isize::MAX + 1 does count as overflow - if let Err(CapacityOverflow) = empty_string.try_reserve(MAX_CAP + 1) { - } else { - panic!("isize::MAX + 1 should trigger an overflow!") - } - - // Check usize::MAX does count as overflow - if let Err(CapacityOverflow) = empty_string.try_reserve(MAX_USIZE) { - } else { - panic!("usize::MAX should trigger an overflow!") - } - } else { - // Check isize::MAX + 1 is an OOM - if let Err(AllocError { .. }) = empty_string.try_reserve(MAX_CAP + 1) { - } else { - panic!("isize::MAX + 1 should trigger an OOM!") - } - - // Check usize::MAX is an OOM - if let Err(AllocError { .. }) = empty_string.try_reserve(MAX_USIZE) { - } else { - panic!("usize::MAX should trigger an OOM!") - } - } - } - - { - // Same basic idea, but with non-zero len - let mut ten_bytes: String = String::from("0123456789"); - - if let Err(CapacityOverflow) = ten_bytes.try_reserve(MAX_CAP - 10) { - panic!("isize::MAX shouldn't trigger an overflow!"); - } - if let Err(CapacityOverflow) = ten_bytes.try_reserve(MAX_CAP - 10) { - panic!("isize::MAX shouldn't trigger an overflow!"); - } - if guards_against_isize { - if let Err(CapacityOverflow) = ten_bytes.try_reserve(MAX_CAP - 9) { - } else { - panic!("isize::MAX + 1 should trigger an overflow!"); - } - } else { - if let Err(AllocError { .. }) = ten_bytes.try_reserve(MAX_CAP - 9) { - } else { - panic!("isize::MAX + 1 should trigger an OOM!") - } - } - // Should always overflow in the add-to-len - if let Err(CapacityOverflow) = ten_bytes.try_reserve(MAX_USIZE) { - } else { - panic!("usize::MAX should trigger an overflow!") - } - } -} - -#[test] -#[cfg_attr(miri, ignore)] // Miri does not support signalling OOM -#[cfg_attr(target_os = "android", ignore)] // Android used in CI has a broken dlmalloc -fn test_try_reserve_exact() { - // This is exactly the same as test_try_reserve with the method changed. - // See that test for comments. - - const MAX_CAP: usize = isize::MAX as usize; - const MAX_USIZE: usize = usize::MAX; - - let guards_against_isize = size_of::<usize>() < 8; - - { - let mut empty_string: String = String::new(); - - if let Err(CapacityOverflow) = empty_string.try_reserve_exact(MAX_CAP) { - panic!("isize::MAX shouldn't trigger an overflow!"); - } - if let Err(CapacityOverflow) = empty_string.try_reserve_exact(MAX_CAP) { - panic!("isize::MAX shouldn't trigger an overflow!"); - } - - if guards_against_isize { - if let Err(CapacityOverflow) = empty_string.try_reserve_exact(MAX_CAP + 1) { - } else { - panic!("isize::MAX + 1 should trigger an overflow!") - } - - if let Err(CapacityOverflow) = empty_string.try_reserve_exact(MAX_USIZE) { - } else { - panic!("usize::MAX should trigger an overflow!") - } - } else { - if let Err(AllocError { .. }) = empty_string.try_reserve_exact(MAX_CAP + 1) { - } else { - panic!("isize::MAX + 1 should trigger an OOM!") - } - - if let Err(AllocError { .. }) = empty_string.try_reserve_exact(MAX_USIZE) { - } else { - panic!("usize::MAX should trigger an OOM!") - } - } - } - - { - let mut ten_bytes: String = String::from("0123456789"); - - if let Err(CapacityOverflow) = ten_bytes.try_reserve_exact(MAX_CAP - 10) { - panic!("isize::MAX shouldn't trigger an overflow!"); - } - if let Err(CapacityOverflow) = ten_bytes.try_reserve_exact(MAX_CAP - 10) { - panic!("isize::MAX shouldn't trigger an overflow!"); - } - if guards_against_isize { - if let Err(CapacityOverflow) = ten_bytes.try_reserve_exact(MAX_CAP - 9) { - } else { - panic!("isize::MAX + 1 should trigger an overflow!"); - } - } else { - if let Err(AllocError { .. }) = ten_bytes.try_reserve_exact(MAX_CAP - 9) { - } else { - panic!("isize::MAX + 1 should trigger an OOM!") - } - } - if let Err(CapacityOverflow) = ten_bytes.try_reserve_exact(MAX_USIZE) { - } else { - panic!("usize::MAX should trigger an overflow!") - } - } -} - -#[test] -fn test_from_char() { - assert_eq!(String::from('a'), 'a'.to_string()); - let s: String = 'x'.into(); - assert_eq!(s, 'x'.to_string()); -} diff --git a/src/liballoc/tests/vec.rs b/src/liballoc/tests/vec.rs deleted file mode 100644 index ffff543b07f..00000000000 --- a/src/liballoc/tests/vec.rs +++ /dev/null @@ -1,1629 +0,0 @@ -use std::borrow::Cow; -use std::collections::TryReserveError::*; -use std::fmt::Debug; -use std::mem::size_of; -use std::panic::{catch_unwind, AssertUnwindSafe}; -use std::vec::{Drain, IntoIter}; - -struct DropCounter<'a> { - count: &'a mut u32, -} - -impl Drop for DropCounter<'_> { - fn drop(&mut self) { - *self.count += 1; - } -} - -#[test] -fn test_small_vec_struct() { - assert_eq!(size_of::<Vec<u8>>(), size_of::<usize>() * 3); -} - -#[test] -fn test_double_drop() { - struct TwoVec<T> { - x: Vec<T>, - y: Vec<T>, - } - - let (mut count_x, mut count_y) = (0, 0); - { - let mut tv = TwoVec { x: Vec::new(), y: Vec::new() }; - tv.x.push(DropCounter { count: &mut count_x }); - tv.y.push(DropCounter { count: &mut count_y }); - - // If Vec had a drop flag, here is where it would be zeroed. - // Instead, it should rely on its internal state to prevent - // doing anything significant when dropped multiple times. - drop(tv.x); - - // Here tv goes out of scope, tv.y should be dropped, but not tv.x. - } - - assert_eq!(count_x, 1); - assert_eq!(count_y, 1); -} - -#[test] -fn test_reserve() { - let mut v = Vec::new(); - assert_eq!(v.capacity(), 0); - - v.reserve(2); - assert!(v.capacity() >= 2); - - for i in 0..16 { - v.push(i); - } - - assert!(v.capacity() >= 16); - v.reserve(16); - assert!(v.capacity() >= 32); - - v.push(16); - - v.reserve(16); - assert!(v.capacity() >= 33) -} - -#[test] -fn test_zst_capacity() { - assert_eq!(Vec::<()>::new().capacity(), usize::MAX); -} - -#[test] -fn test_extend() { - let mut v = Vec::new(); - let mut w = Vec::new(); - - v.extend(w.clone()); - assert_eq!(v, &[]); - - v.extend(0..3); - for i in 0..3 { - w.push(i) - } - - assert_eq!(v, w); - - v.extend(3..10); - for i in 3..10 { - w.push(i) - } - - assert_eq!(v, w); - - v.extend(w.clone()); // specializes to `append` - assert!(v.iter().eq(w.iter().chain(w.iter()))); - - // Zero sized types - #[derive(PartialEq, Debug)] - struct Foo; - - let mut a = Vec::new(); - let b = vec![Foo, Foo]; - - a.extend(b); - assert_eq!(a, &[Foo, Foo]); - - // Double drop - let mut count_x = 0; - { - let mut x = Vec::new(); - let y = vec![DropCounter { count: &mut count_x }]; - x.extend(y); - } - assert_eq!(count_x, 1); -} - -#[test] -fn test_extend_ref() { - let mut v = vec![1, 2]; - v.extend(&[3, 4, 5]); - - assert_eq!(v.len(), 5); - assert_eq!(v, [1, 2, 3, 4, 5]); - - let w = vec![6, 7]; - v.extend(&w); - - assert_eq!(v.len(), 7); - assert_eq!(v, [1, 2, 3, 4, 5, 6, 7]); -} - -#[test] -fn test_slice_from_mut() { - let mut values = vec![1, 2, 3, 4, 5]; - { - let slice = &mut values[2..]; - assert!(slice == [3, 4, 5]); - for p in slice { - *p += 2; - } - } - - assert!(values == [1, 2, 5, 6, 7]); -} - -#[test] -fn test_slice_to_mut() { - let mut values = vec![1, 2, 3, 4, 5]; - { - let slice = &mut values[..2]; - assert!(slice == [1, 2]); - for p in slice { - *p += 1; - } - } - - assert!(values == [2, 3, 3, 4, 5]); -} - -#[test] -fn test_split_at_mut() { - let mut values = vec![1, 2, 3, 4, 5]; - { - let (left, right) = values.split_at_mut(2); - { - let left: &[_] = left; - assert!(&left[..left.len()] == &[1, 2]); - } - for p in left { - *p += 1; - } - - { - let right: &[_] = right; - assert!(&right[..right.len()] == &[3, 4, 5]); - } - for p in right { - *p += 2; - } - } - - assert_eq!(values, [2, 3, 5, 6, 7]); -} - -#[test] -fn test_clone() { - let v: Vec<i32> = vec![]; - let w = vec![1, 2, 3]; - - assert_eq!(v, v.clone()); - - let z = w.clone(); - assert_eq!(w, z); - // they should be disjoint in memory. - assert!(w.as_ptr() != z.as_ptr()) -} - -#[test] -fn test_clone_from() { - let mut v = vec![]; - let three: Vec<Box<_>> = vec![box 1, box 2, box 3]; - let two: Vec<Box<_>> = vec![box 4, box 5]; - // zero, long - v.clone_from(&three); - assert_eq!(v, three); - - // equal - v.clone_from(&three); - assert_eq!(v, three); - - // long, short - v.clone_from(&two); - assert_eq!(v, two); - - // short, long - v.clone_from(&three); - assert_eq!(v, three) -} - -#[test] -fn test_retain() { - let mut vec = vec![1, 2, 3, 4]; - vec.retain(|&x| x % 2 == 0); - assert_eq!(vec, [2, 4]); -} - -#[test] -fn test_dedup() { - fn case(a: Vec<i32>, b: Vec<i32>) { - let mut v = a; - v.dedup(); - assert_eq!(v, b); - } - case(vec![], vec![]); - case(vec![1], vec![1]); - case(vec![1, 1], vec![1]); - case(vec![1, 2, 3], vec![1, 2, 3]); - case(vec![1, 1, 2, 3], vec![1, 2, 3]); - case(vec![1, 2, 2, 3], vec![1, 2, 3]); - case(vec![1, 2, 3, 3], vec![1, 2, 3]); - case(vec![1, 1, 2, 2, 2, 3, 3], vec![1, 2, 3]); -} - -#[test] -fn test_dedup_by_key() { - fn case(a: Vec<i32>, b: Vec<i32>) { - let mut v = a; - v.dedup_by_key(|i| *i / 10); - assert_eq!(v, b); - } - case(vec![], vec![]); - case(vec![10], vec![10]); - case(vec![10, 11], vec![10]); - case(vec![10, 20, 30], vec![10, 20, 30]); - case(vec![10, 11, 20, 30], vec![10, 20, 30]); - case(vec![10, 20, 21, 30], vec![10, 20, 30]); - case(vec![10, 20, 30, 31], vec![10, 20, 30]); - case(vec![10, 11, 20, 21, 22, 30, 31], vec![10, 20, 30]); -} - -#[test] -fn test_dedup_by() { - let mut vec = vec!["foo", "bar", "Bar", "baz", "bar"]; - vec.dedup_by(|a, b| a.eq_ignore_ascii_case(b)); - - assert_eq!(vec, ["foo", "bar", "baz", "bar"]); - - let mut vec = vec![("foo", 1), ("foo", 2), ("bar", 3), ("bar", 4), ("bar", 5)]; - vec.dedup_by(|a, b| { - a.0 == b.0 && { - b.1 += a.1; - true - } - }); - - assert_eq!(vec, [("foo", 3), ("bar", 12)]); -} - -#[test] -fn test_dedup_unique() { - let mut v0: Vec<Box<_>> = vec![box 1, box 1, box 2, box 3]; - v0.dedup(); - let mut v1: Vec<Box<_>> = vec![box 1, box 2, box 2, box 3]; - v1.dedup(); - let mut v2: Vec<Box<_>> = vec![box 1, box 2, box 3, box 3]; - v2.dedup(); - // If the boxed pointers were leaked or otherwise misused, valgrind - // and/or rt should raise errors. -} - -#[test] -fn zero_sized_values() { - let mut v = Vec::new(); - assert_eq!(v.len(), 0); - v.push(()); - assert_eq!(v.len(), 1); - v.push(()); - assert_eq!(v.len(), 2); - assert_eq!(v.pop(), Some(())); - assert_eq!(v.pop(), Some(())); - assert_eq!(v.pop(), None); - - assert_eq!(v.iter().count(), 0); - v.push(()); - assert_eq!(v.iter().count(), 1); - v.push(()); - assert_eq!(v.iter().count(), 2); - - for &() in &v {} - - assert_eq!(v.iter_mut().count(), 2); - v.push(()); - assert_eq!(v.iter_mut().count(), 3); - v.push(()); - assert_eq!(v.iter_mut().count(), 4); - - for &mut () in &mut v {} - unsafe { - v.set_len(0); - } - assert_eq!(v.iter_mut().count(), 0); -} - -#[test] -fn test_partition() { - assert_eq!(vec![].into_iter().partition(|x: &i32| *x < 3), (vec![], vec![])); - assert_eq!(vec![1, 2, 3].into_iter().partition(|x| *x < 4), (vec![1, 2, 3], vec![])); - assert_eq!(vec![1, 2, 3].into_iter().partition(|x| *x < 2), (vec![1], vec![2, 3])); - assert_eq!(vec![1, 2, 3].into_iter().partition(|x| *x < 0), (vec![], vec![1, 2, 3])); -} - -#[test] -fn test_zip_unzip() { - let z1 = vec![(1, 4), (2, 5), (3, 6)]; - - let (left, right): (Vec<_>, Vec<_>) = z1.iter().cloned().unzip(); - - assert_eq!((1, 4), (left[0], right[0])); - assert_eq!((2, 5), (left[1], right[1])); - assert_eq!((3, 6), (left[2], right[2])); -} - -#[test] -fn test_vec_truncate_drop() { - static mut DROPS: u32 = 0; - struct Elem(i32); - impl Drop for Elem { - fn drop(&mut self) { - unsafe { - DROPS += 1; - } - } - } - - let mut v = vec![Elem(1), Elem(2), Elem(3), Elem(4), Elem(5)]; - assert_eq!(unsafe { DROPS }, 0); - v.truncate(3); - assert_eq!(unsafe { DROPS }, 2); - v.truncate(0); - assert_eq!(unsafe { DROPS }, 5); -} - -#[test] -#[should_panic] -fn test_vec_truncate_fail() { - struct BadElem(i32); - impl Drop for BadElem { - fn drop(&mut self) { - let BadElem(ref mut x) = *self; - if *x == 0xbadbeef { - panic!("BadElem panic: 0xbadbeef") - } - } - } - - let mut v = vec![BadElem(1), BadElem(2), BadElem(0xbadbeef), BadElem(4)]; - v.truncate(0); -} - -#[test] -fn test_index() { - let vec = vec![1, 2, 3]; - assert!(vec[1] == 2); -} - -#[test] -#[should_panic] -fn test_index_out_of_bounds() { - let vec = vec![1, 2, 3]; - let _ = vec[3]; -} - -#[test] -#[should_panic] -fn test_slice_out_of_bounds_1() { - let x = vec![1, 2, 3, 4, 5]; - &x[!0..]; -} - -#[test] -#[should_panic] -fn test_slice_out_of_bounds_2() { - let x = vec![1, 2, 3, 4, 5]; - &x[..6]; -} - -#[test] -#[should_panic] -fn test_slice_out_of_bounds_3() { - let x = vec![1, 2, 3, 4, 5]; - &x[!0..4]; -} - -#[test] -#[should_panic] -fn test_slice_out_of_bounds_4() { - let x = vec![1, 2, 3, 4, 5]; - &x[1..6]; -} - -#[test] -#[should_panic] -fn test_slice_out_of_bounds_5() { - let x = vec![1, 2, 3, 4, 5]; - &x[3..2]; -} - -#[test] -#[should_panic] -fn test_swap_remove_empty() { - let mut vec = Vec::<i32>::new(); - vec.swap_remove(0); -} - -#[test] -fn test_move_items() { - let vec = vec![1, 2, 3]; - let mut vec2 = vec![]; - for i in vec { - vec2.push(i); - } - assert_eq!(vec2, [1, 2, 3]); -} - -#[test] -fn test_move_items_reverse() { - let vec = vec![1, 2, 3]; - let mut vec2 = vec![]; - for i in vec.into_iter().rev() { - vec2.push(i); - } - assert_eq!(vec2, [3, 2, 1]); -} - -#[test] -fn test_move_items_zero_sized() { - let vec = vec![(), (), ()]; - let mut vec2 = vec![]; - for i in vec { - vec2.push(i); - } - assert_eq!(vec2, [(), (), ()]); -} - -#[test] -fn test_drain_items() { - let mut vec = vec![1, 2, 3]; - let mut vec2 = vec![]; - for i in vec.drain(..) { - vec2.push(i); - } - assert_eq!(vec, []); - assert_eq!(vec2, [1, 2, 3]); -} - -#[test] -fn test_drain_items_reverse() { - let mut vec = vec![1, 2, 3]; - let mut vec2 = vec![]; - for i in vec.drain(..).rev() { - vec2.push(i); - } - assert_eq!(vec, []); - assert_eq!(vec2, [3, 2, 1]); -} - -#[test] -fn test_drain_items_zero_sized() { - let mut vec = vec![(), (), ()]; - let mut vec2 = vec![]; - for i in vec.drain(..) { - vec2.push(i); - } - assert_eq!(vec, []); - assert_eq!(vec2, [(), (), ()]); -} - -#[test] -#[should_panic] -fn test_drain_out_of_bounds() { - let mut v = vec![1, 2, 3, 4, 5]; - v.drain(5..6); -} - -#[test] -fn test_drain_range() { - let mut v = vec![1, 2, 3, 4, 5]; - for _ in v.drain(4..) {} - assert_eq!(v, &[1, 2, 3, 4]); - - let mut v: Vec<_> = (1..6).map(|x| x.to_string()).collect(); - for _ in v.drain(1..4) {} - assert_eq!(v, &[1.to_string(), 5.to_string()]); - - let mut v: Vec<_> = (1..6).map(|x| x.to_string()).collect(); - for _ in v.drain(1..4).rev() {} - assert_eq!(v, &[1.to_string(), 5.to_string()]); - - let mut v: Vec<_> = vec![(); 5]; - for _ in v.drain(1..4).rev() {} - assert_eq!(v, &[(), ()]); -} - -#[test] -fn test_drain_inclusive_range() { - let mut v = vec!['a', 'b', 'c', 'd', 'e']; - for _ in v.drain(1..=3) {} - assert_eq!(v, &['a', 'e']); - - let mut v: Vec<_> = (0..=5).map(|x| x.to_string()).collect(); - for _ in v.drain(1..=5) {} - assert_eq!(v, &["0".to_string()]); - - let mut v: Vec<String> = (0..=5).map(|x| x.to_string()).collect(); - for _ in v.drain(0..=5) {} - assert_eq!(v, Vec::<String>::new()); - - let mut v: Vec<_> = (0..=5).map(|x| x.to_string()).collect(); - for _ in v.drain(0..=3) {} - assert_eq!(v, &["4".to_string(), "5".to_string()]); - - let mut v: Vec<_> = (0..=1).map(|x| x.to_string()).collect(); - for _ in v.drain(..=0) {} - assert_eq!(v, &["1".to_string()]); -} - -#[test] -fn test_drain_max_vec_size() { - let mut v = Vec::<()>::with_capacity(usize::MAX); - unsafe { - v.set_len(usize::MAX); - } - for _ in v.drain(usize::MAX - 1..) {} - assert_eq!(v.len(), usize::MAX - 1); - - let mut v = Vec::<()>::with_capacity(usize::MAX); - unsafe { - v.set_len(usize::MAX); - } - for _ in v.drain(usize::MAX - 1..=usize::MAX - 1) {} - assert_eq!(v.len(), usize::MAX - 1); -} - -#[test] -#[should_panic] -fn test_drain_inclusive_out_of_bounds() { - let mut v = vec![1, 2, 3, 4, 5]; - v.drain(5..=5); -} - -#[test] -fn test_drain_leak() { - static mut DROPS: i32 = 0; - - #[derive(Debug, PartialEq)] - struct D(u32, bool); - - impl Drop for D { - fn drop(&mut self) { - unsafe { - DROPS += 1; - } - - if self.1 { - panic!("panic in `drop`"); - } - } - } - - let mut v = vec![ - D(0, false), - D(1, false), - D(2, false), - D(3, false), - D(4, true), - D(5, false), - D(6, false), - ]; - - catch_unwind(AssertUnwindSafe(|| { - v.drain(2..=5); - })) - .ok(); - - assert_eq!(unsafe { DROPS }, 4); - assert_eq!(v, vec![D(0, false), D(1, false), D(6, false),]); -} - -#[test] -fn test_splice() { - let mut v = vec![1, 2, 3, 4, 5]; - let a = [10, 11, 12]; - v.splice(2..4, a.iter().cloned()); - assert_eq!(v, &[1, 2, 10, 11, 12, 5]); - v.splice(1..3, Some(20)); - assert_eq!(v, &[1, 20, 11, 12, 5]); -} - -#[test] -fn test_splice_inclusive_range() { - let mut v = vec![1, 2, 3, 4, 5]; - let a = [10, 11, 12]; - let t1: Vec<_> = v.splice(2..=3, a.iter().cloned()).collect(); - assert_eq!(v, &[1, 2, 10, 11, 12, 5]); - assert_eq!(t1, &[3, 4]); - let t2: Vec<_> = v.splice(1..=2, Some(20)).collect(); - assert_eq!(v, &[1, 20, 11, 12, 5]); - assert_eq!(t2, &[2, 10]); -} - -#[test] -#[should_panic] -fn test_splice_out_of_bounds() { - let mut v = vec![1, 2, 3, 4, 5]; - let a = [10, 11, 12]; - v.splice(5..6, a.iter().cloned()); -} - -#[test] -#[should_panic] -fn test_splice_inclusive_out_of_bounds() { - let mut v = vec![1, 2, 3, 4, 5]; - let a = [10, 11, 12]; - v.splice(5..=5, a.iter().cloned()); -} - -#[test] -fn test_splice_items_zero_sized() { - let mut vec = vec![(), (), ()]; - let vec2 = vec![]; - let t: Vec<_> = vec.splice(1..2, vec2.iter().cloned()).collect(); - assert_eq!(vec, &[(), ()]); - assert_eq!(t, &[()]); -} - -#[test] -fn test_splice_unbounded() { - let mut vec = vec![1, 2, 3, 4, 5]; - let t: Vec<_> = vec.splice(.., None).collect(); - assert_eq!(vec, &[]); - assert_eq!(t, &[1, 2, 3, 4, 5]); -} - -#[test] -fn test_splice_forget() { - let mut v = vec![1, 2, 3, 4, 5]; - let a = [10, 11, 12]; - std::mem::forget(v.splice(2..4, a.iter().cloned())); - assert_eq!(v, &[1, 2]); -} - -#[test] -fn test_into_boxed_slice() { - let xs = vec![1, 2, 3]; - let ys = xs.into_boxed_slice(); - assert_eq!(&*ys, [1, 2, 3]); -} - -#[test] -fn test_append() { - let mut vec = vec![1, 2, 3]; - let mut vec2 = vec![4, 5, 6]; - vec.append(&mut vec2); - assert_eq!(vec, [1, 2, 3, 4, 5, 6]); - assert_eq!(vec2, []); -} - -#[test] -fn test_split_off() { - let mut vec = vec![1, 2, 3, 4, 5, 6]; - let vec2 = vec.split_off(4); - assert_eq!(vec, [1, 2, 3, 4]); - assert_eq!(vec2, [5, 6]); -} - -#[test] -fn test_into_iter_as_slice() { - let vec = vec!['a', 'b', 'c']; - let mut into_iter = vec.into_iter(); - assert_eq!(into_iter.as_slice(), &['a', 'b', 'c']); - let _ = into_iter.next().unwrap(); - assert_eq!(into_iter.as_slice(), &['b', 'c']); - let _ = into_iter.next().unwrap(); - let _ = into_iter.next().unwrap(); - assert_eq!(into_iter.as_slice(), &[]); -} - -#[test] -fn test_into_iter_as_mut_slice() { - let vec = vec!['a', 'b', 'c']; - let mut into_iter = vec.into_iter(); - assert_eq!(into_iter.as_slice(), &['a', 'b', 'c']); - into_iter.as_mut_slice()[0] = 'x'; - into_iter.as_mut_slice()[1] = 'y'; - assert_eq!(into_iter.next().unwrap(), 'x'); - assert_eq!(into_iter.as_slice(), &['y', 'c']); -} - -#[test] -fn test_into_iter_debug() { - let vec = vec!['a', 'b', 'c']; - let into_iter = vec.into_iter(); - let debug = format!("{:?}", into_iter); - assert_eq!(debug, "IntoIter(['a', 'b', 'c'])"); -} - -#[test] -fn test_into_iter_count() { - assert_eq!(vec![1, 2, 3].into_iter().count(), 3); -} - -#[test] -fn test_into_iter_clone() { - fn iter_equal<I: Iterator<Item = i32>>(it: I, slice: &[i32]) { - let v: Vec<i32> = it.collect(); - assert_eq!(&v[..], slice); - } - let mut it = vec![1, 2, 3].into_iter(); - iter_equal(it.clone(), &[1, 2, 3]); - assert_eq!(it.next(), Some(1)); - let mut it = it.rev(); - iter_equal(it.clone(), &[3, 2]); - assert_eq!(it.next(), Some(3)); - iter_equal(it.clone(), &[2]); - assert_eq!(it.next(), Some(2)); - iter_equal(it.clone(), &[]); - assert_eq!(it.next(), None); -} - -#[test] -fn test_into_iter_leak() { - static mut DROPS: i32 = 0; - - struct D(bool); - - impl Drop for D { - fn drop(&mut self) { - unsafe { - DROPS += 1; - } - - if self.0 { - panic!("panic in `drop`"); - } - } - } - - let v = vec![D(false), D(true), D(false)]; - - catch_unwind(move || drop(v.into_iter())).ok(); - - assert_eq!(unsafe { DROPS }, 3); -} - -#[test] -fn test_cow_from() { - let borrowed: &[_] = &["borrowed", "(slice)"]; - let owned = vec!["owned", "(vec)"]; - match (Cow::from(owned.clone()), Cow::from(borrowed)) { - (Cow::Owned(o), Cow::Borrowed(b)) => assert!(o == owned && b == borrowed), - _ => panic!("invalid `Cow::from`"), - } -} - -#[test] -fn test_from_cow() { - let borrowed: &[_] = &["borrowed", "(slice)"]; - let owned = vec!["owned", "(vec)"]; - assert_eq!(Vec::from(Cow::Borrowed(borrowed)), vec!["borrowed", "(slice)"]); - assert_eq!(Vec::from(Cow::Owned(owned)), vec!["owned", "(vec)"]); -} - -#[allow(dead_code)] -fn assert_covariance() { - fn drain<'new>(d: Drain<'static, &'static str>) -> Drain<'new, &'new str> { - d - } - fn into_iter<'new>(i: IntoIter<&'static str>) -> IntoIter<&'new str> { - i - } -} - -#[test] -fn from_into_inner() { - let vec = vec![1, 2, 3]; - let ptr = vec.as_ptr(); - let vec = vec.into_iter().collect::<Vec<_>>(); - assert_eq!(vec, [1, 2, 3]); - assert_eq!(vec.as_ptr(), ptr); - - let ptr = &vec[1] as *const _; - let mut it = vec.into_iter(); - it.next().unwrap(); - let vec = it.collect::<Vec<_>>(); - assert_eq!(vec, [2, 3]); - assert!(ptr != vec.as_ptr()); -} - -#[test] -fn overaligned_allocations() { - #[repr(align(256))] - struct Foo(usize); - let mut v = vec![Foo(273)]; - for i in 0..0x1000 { - v.reserve_exact(i); - assert!(v[0].0 == 273); - assert!(v.as_ptr() as usize & 0xff == 0); - v.shrink_to_fit(); - assert!(v[0].0 == 273); - assert!(v.as_ptr() as usize & 0xff == 0); - } -} - -#[test] -fn drain_filter_empty() { - let mut vec: Vec<i32> = vec![]; - - { - let mut iter = vec.drain_filter(|_| true); - assert_eq!(iter.size_hint(), (0, Some(0))); - assert_eq!(iter.next(), None); - assert_eq!(iter.size_hint(), (0, Some(0))); - assert_eq!(iter.next(), None); - assert_eq!(iter.size_hint(), (0, Some(0))); - } - assert_eq!(vec.len(), 0); - assert_eq!(vec, vec![]); -} - -#[test] -fn drain_filter_zst() { - let mut vec = vec![(), (), (), (), ()]; - let initial_len = vec.len(); - let mut count = 0; - { - let mut iter = vec.drain_filter(|_| true); - assert_eq!(iter.size_hint(), (0, Some(initial_len))); - while let Some(_) = iter.next() { - count += 1; - assert_eq!(iter.size_hint(), (0, Some(initial_len - count))); - } - assert_eq!(iter.size_hint(), (0, Some(0))); - assert_eq!(iter.next(), None); - assert_eq!(iter.size_hint(), (0, Some(0))); - } - - assert_eq!(count, initial_len); - assert_eq!(vec.len(), 0); - assert_eq!(vec, vec![]); -} - -#[test] -fn drain_filter_false() { - let mut vec = vec![1, 2, 3, 4, 5, 6, 7, 8, 9, 10]; - - let initial_len = vec.len(); - let mut count = 0; - { - let mut iter = vec.drain_filter(|_| false); - assert_eq!(iter.size_hint(), (0, Some(initial_len))); - for _ in iter.by_ref() { - count += 1; - } - assert_eq!(iter.size_hint(), (0, Some(0))); - assert_eq!(iter.next(), None); - assert_eq!(iter.size_hint(), (0, Some(0))); - } - - assert_eq!(count, 0); - assert_eq!(vec.len(), initial_len); - assert_eq!(vec, vec![1, 2, 3, 4, 5, 6, 7, 8, 9, 10]); -} - -#[test] -fn drain_filter_true() { - let mut vec = vec![1, 2, 3, 4, 5, 6, 7, 8, 9, 10]; - - let initial_len = vec.len(); - let mut count = 0; - { - let mut iter = vec.drain_filter(|_| true); - assert_eq!(iter.size_hint(), (0, Some(initial_len))); - while let Some(_) = iter.next() { - count += 1; - assert_eq!(iter.size_hint(), (0, Some(initial_len - count))); - } - assert_eq!(iter.size_hint(), (0, Some(0))); - assert_eq!(iter.next(), None); - assert_eq!(iter.size_hint(), (0, Some(0))); - } - - assert_eq!(count, initial_len); - assert_eq!(vec.len(), 0); - assert_eq!(vec, vec![]); -} - -#[test] -fn drain_filter_complex() { - { - // [+xxx++++++xxxxx++++x+x++] - let mut vec = vec![ - 1, 2, 4, 6, 7, 9, 11, 13, 15, 17, 18, 20, 22, 24, 26, 27, 29, 31, 33, 34, 35, 36, 37, - 39, - ]; - - let removed = vec.drain_filter(|x| *x % 2 == 0).collect::<Vec<_>>(); - assert_eq!(removed.len(), 10); - assert_eq!(removed, vec![2, 4, 6, 18, 20, 22, 24, 26, 34, 36]); - - assert_eq!(vec.len(), 14); - assert_eq!(vec, vec![1, 7, 9, 11, 13, 15, 17, 27, 29, 31, 33, 35, 37, 39]); - } - - { - // [xxx++++++xxxxx++++x+x++] - let mut vec = vec![ - 2, 4, 6, 7, 9, 11, 13, 15, 17, 18, 20, 22, 24, 26, 27, 29, 31, 33, 34, 35, 36, 37, 39, - ]; - - let removed = vec.drain_filter(|x| *x % 2 == 0).collect::<Vec<_>>(); - assert_eq!(removed.len(), 10); - assert_eq!(removed, vec![2, 4, 6, 18, 20, 22, 24, 26, 34, 36]); - - assert_eq!(vec.len(), 13); - assert_eq!(vec, vec![7, 9, 11, 13, 15, 17, 27, 29, 31, 33, 35, 37, 39]); - } - - { - // [xxx++++++xxxxx++++x+x] - let mut vec = - vec![2, 4, 6, 7, 9, 11, 13, 15, 17, 18, 20, 22, 24, 26, 27, 29, 31, 33, 34, 35, 36]; - - let removed = vec.drain_filter(|x| *x % 2 == 0).collect::<Vec<_>>(); - assert_eq!(removed.len(), 10); - assert_eq!(removed, vec![2, 4, 6, 18, 20, 22, 24, 26, 34, 36]); - - assert_eq!(vec.len(), 11); - assert_eq!(vec, vec![7, 9, 11, 13, 15, 17, 27, 29, 31, 33, 35]); - } - - { - // [xxxxxxxxxx+++++++++++] - let mut vec = vec![2, 4, 6, 8, 10, 12, 14, 16, 18, 20, 1, 3, 5, 7, 9, 11, 13, 15, 17, 19]; - - let removed = vec.drain_filter(|x| *x % 2 == 0).collect::<Vec<_>>(); - assert_eq!(removed.len(), 10); - assert_eq!(removed, vec![2, 4, 6, 8, 10, 12, 14, 16, 18, 20]); - - assert_eq!(vec.len(), 10); - assert_eq!(vec, vec![1, 3, 5, 7, 9, 11, 13, 15, 17, 19]); - } - - { - // [+++++++++++xxxxxxxxxx] - let mut vec = vec![1, 3, 5, 7, 9, 11, 13, 15, 17, 19, 2, 4, 6, 8, 10, 12, 14, 16, 18, 20]; - - let removed = vec.drain_filter(|x| *x % 2 == 0).collect::<Vec<_>>(); - assert_eq!(removed.len(), 10); - assert_eq!(removed, vec![2, 4, 6, 8, 10, 12, 14, 16, 18, 20]); - - assert_eq!(vec.len(), 10); - assert_eq!(vec, vec![1, 3, 5, 7, 9, 11, 13, 15, 17, 19]); - } -} - -// FIXME: re-enable emscripten once it can unwind again -#[test] -#[cfg(not(target_os = "emscripten"))] -fn drain_filter_consumed_panic() { - use std::rc::Rc; - use std::sync::Mutex; - - struct Check { - index: usize, - drop_counts: Rc<Mutex<Vec<usize>>>, - }; - - impl Drop for Check { - fn drop(&mut self) { - self.drop_counts.lock().unwrap()[self.index] += 1; - println!("drop: {}", self.index); - } - } - - let check_count = 10; - let drop_counts = Rc::new(Mutex::new(vec![0_usize; check_count])); - let mut data: Vec<Check> = (0..check_count) - .map(|index| Check { index, drop_counts: Rc::clone(&drop_counts) }) - .collect(); - - let _ = std::panic::catch_unwind(move || { - let filter = |c: &mut Check| { - if c.index == 2 { - panic!("panic at index: {}", c.index); - } - // Verify that if the filter could panic again on another element - // that it would not cause a double panic and all elements of the - // vec would still be dropped exactly once. - if c.index == 4 { - panic!("panic at index: {}", c.index); - } - c.index < 6 - }; - let drain = data.drain_filter(filter); - - // NOTE: The DrainFilter is explicitly consumed - drain.for_each(drop); - }); - - let drop_counts = drop_counts.lock().unwrap(); - assert_eq!(check_count, drop_counts.len()); - - for (index, count) in drop_counts.iter().cloned().enumerate() { - assert_eq!(1, count, "unexpected drop count at index: {} (count: {})", index, count); - } -} - -// FIXME: Re-enable emscripten once it can catch panics -#[test] -#[cfg(not(target_os = "emscripten"))] -fn drain_filter_unconsumed_panic() { - use std::rc::Rc; - use std::sync::Mutex; - - struct Check { - index: usize, - drop_counts: Rc<Mutex<Vec<usize>>>, - }; - - impl Drop for Check { - fn drop(&mut self) { - self.drop_counts.lock().unwrap()[self.index] += 1; - println!("drop: {}", self.index); - } - } - - let check_count = 10; - let drop_counts = Rc::new(Mutex::new(vec![0_usize; check_count])); - let mut data: Vec<Check> = (0..check_count) - .map(|index| Check { index, drop_counts: Rc::clone(&drop_counts) }) - .collect(); - - let _ = std::panic::catch_unwind(move || { - let filter = |c: &mut Check| { - if c.index == 2 { - panic!("panic at index: {}", c.index); - } - // Verify that if the filter could panic again on another element - // that it would not cause a double panic and all elements of the - // vec would still be dropped exactly once. - if c.index == 4 { - panic!("panic at index: {}", c.index); - } - c.index < 6 - }; - let _drain = data.drain_filter(filter); - - // NOTE: The DrainFilter is dropped without being consumed - }); - - let drop_counts = drop_counts.lock().unwrap(); - assert_eq!(check_count, drop_counts.len()); - - for (index, count) in drop_counts.iter().cloned().enumerate() { - assert_eq!(1, count, "unexpected drop count at index: {} (count: {})", index, count); - } -} - -#[test] -fn drain_filter_unconsumed() { - let mut vec = vec![1, 2, 3, 4]; - let drain = vec.drain_filter(|&mut x| x % 2 != 0); - drop(drain); - assert_eq!(vec, [2, 4]); -} - -#[test] -fn test_reserve_exact() { - // This is all the same as test_reserve - - let mut v = Vec::new(); - assert_eq!(v.capacity(), 0); - - v.reserve_exact(2); - assert!(v.capacity() >= 2); - - for i in 0..16 { - v.push(i); - } - - assert!(v.capacity() >= 16); - v.reserve_exact(16); - assert!(v.capacity() >= 32); - - v.push(16); - - v.reserve_exact(16); - assert!(v.capacity() >= 33) -} - -#[test] -#[cfg_attr(miri, ignore)] // Miri does not support signalling OOM -#[cfg_attr(target_os = "android", ignore)] // Android used in CI has a broken dlmalloc -fn test_try_reserve() { - // These are the interesting cases: - // * exactly isize::MAX should never trigger a CapacityOverflow (can be OOM) - // * > isize::MAX should always fail - // * On 16/32-bit should CapacityOverflow - // * On 64-bit should OOM - // * overflow may trigger when adding `len` to `cap` (in number of elements) - // * overflow may trigger when multiplying `new_cap` by size_of::<T> (to get bytes) - - const MAX_CAP: usize = isize::MAX as usize; - const MAX_USIZE: usize = usize::MAX; - - // On 16/32-bit, we check that allocations don't exceed isize::MAX, - // on 64-bit, we assume the OS will give an OOM for such a ridiculous size. - // Any platform that succeeds for these requests is technically broken with - // ptr::offset because LLVM is the worst. - let guards_against_isize = size_of::<usize>() < 8; - - { - // Note: basic stuff is checked by test_reserve - let mut empty_bytes: Vec<u8> = Vec::new(); - - // Check isize::MAX doesn't count as an overflow - if let Err(CapacityOverflow) = empty_bytes.try_reserve(MAX_CAP) { - panic!("isize::MAX shouldn't trigger an overflow!"); - } - // Play it again, frank! (just to be sure) - if let Err(CapacityOverflow) = empty_bytes.try_reserve(MAX_CAP) { - panic!("isize::MAX shouldn't trigger an overflow!"); - } - - if guards_against_isize { - // Check isize::MAX + 1 does count as overflow - if let Err(CapacityOverflow) = empty_bytes.try_reserve(MAX_CAP + 1) { - } else { - panic!("isize::MAX + 1 should trigger an overflow!") - } - - // Check usize::MAX does count as overflow - if let Err(CapacityOverflow) = empty_bytes.try_reserve(MAX_USIZE) { - } else { - panic!("usize::MAX should trigger an overflow!") - } - } else { - // Check isize::MAX + 1 is an OOM - if let Err(AllocError { .. }) = empty_bytes.try_reserve(MAX_CAP + 1) { - } else { - panic!("isize::MAX + 1 should trigger an OOM!") - } - - // Check usize::MAX is an OOM - if let Err(AllocError { .. }) = empty_bytes.try_reserve(MAX_USIZE) { - } else { - panic!("usize::MAX should trigger an OOM!") - } - } - } - - { - // Same basic idea, but with non-zero len - let mut ten_bytes: Vec<u8> = vec![1, 2, 3, 4, 5, 6, 7, 8, 9, 10]; - - if let Err(CapacityOverflow) = ten_bytes.try_reserve(MAX_CAP - 10) { - panic!("isize::MAX shouldn't trigger an overflow!"); - } - if let Err(CapacityOverflow) = ten_bytes.try_reserve(MAX_CAP - 10) { - panic!("isize::MAX shouldn't trigger an overflow!"); - } - if guards_against_isize { - if let Err(CapacityOverflow) = ten_bytes.try_reserve(MAX_CAP - 9) { - } else { - panic!("isize::MAX + 1 should trigger an overflow!"); - } - } else { - if let Err(AllocError { .. }) = ten_bytes.try_reserve(MAX_CAP - 9) { - } else { - panic!("isize::MAX + 1 should trigger an OOM!") - } - } - // Should always overflow in the add-to-len - if let Err(CapacityOverflow) = ten_bytes.try_reserve(MAX_USIZE) { - } else { - panic!("usize::MAX should trigger an overflow!") - } - } - - { - // Same basic idea, but with interesting type size - let mut ten_u32s: Vec<u32> = vec![1, 2, 3, 4, 5, 6, 7, 8, 9, 10]; - - if let Err(CapacityOverflow) = ten_u32s.try_reserve(MAX_CAP / 4 - 10) { - panic!("isize::MAX shouldn't trigger an overflow!"); - } - if let Err(CapacityOverflow) = ten_u32s.try_reserve(MAX_CAP / 4 - 10) { - panic!("isize::MAX shouldn't trigger an overflow!"); - } - if guards_against_isize { - if let Err(CapacityOverflow) = ten_u32s.try_reserve(MAX_CAP / 4 - 9) { - } else { - panic!("isize::MAX + 1 should trigger an overflow!"); - } - } else { - if let Err(AllocError { .. }) = ten_u32s.try_reserve(MAX_CAP / 4 - 9) { - } else { - panic!("isize::MAX + 1 should trigger an OOM!") - } - } - // Should fail in the mul-by-size - if let Err(CapacityOverflow) = ten_u32s.try_reserve(MAX_USIZE - 20) { - } else { - panic!("usize::MAX should trigger an overflow!"); - } - } -} - -#[test] -#[cfg_attr(miri, ignore)] // Miri does not support signalling OOM -#[cfg_attr(target_os = "android", ignore)] // Android used in CI has a broken dlmalloc -fn test_try_reserve_exact() { - // This is exactly the same as test_try_reserve with the method changed. - // See that test for comments. - - const MAX_CAP: usize = isize::MAX as usize; - const MAX_USIZE: usize = usize::MAX; - - let guards_against_isize = size_of::<usize>() < 8; - - { - let mut empty_bytes: Vec<u8> = Vec::new(); - - if let Err(CapacityOverflow) = empty_bytes.try_reserve_exact(MAX_CAP) { - panic!("isize::MAX shouldn't trigger an overflow!"); - } - if let Err(CapacityOverflow) = empty_bytes.try_reserve_exact(MAX_CAP) { - panic!("isize::MAX shouldn't trigger an overflow!"); - } - - if guards_against_isize { - if let Err(CapacityOverflow) = empty_bytes.try_reserve_exact(MAX_CAP + 1) { - } else { - panic!("isize::MAX + 1 should trigger an overflow!") - } - - if let Err(CapacityOverflow) = empty_bytes.try_reserve_exact(MAX_USIZE) { - } else { - panic!("usize::MAX should trigger an overflow!") - } - } else { - if let Err(AllocError { .. }) = empty_bytes.try_reserve_exact(MAX_CAP + 1) { - } else { - panic!("isize::MAX + 1 should trigger an OOM!") - } - - if let Err(AllocError { .. }) = empty_bytes.try_reserve_exact(MAX_USIZE) { - } else { - panic!("usize::MAX should trigger an OOM!") - } - } - } - - { - let mut ten_bytes: Vec<u8> = vec![1, 2, 3, 4, 5, 6, 7, 8, 9, 10]; - - if let Err(CapacityOverflow) = ten_bytes.try_reserve_exact(MAX_CAP - 10) { - panic!("isize::MAX shouldn't trigger an overflow!"); - } - if let Err(CapacityOverflow) = ten_bytes.try_reserve_exact(MAX_CAP - 10) { - panic!("isize::MAX shouldn't trigger an overflow!"); - } - if guards_against_isize { - if let Err(CapacityOverflow) = ten_bytes.try_reserve_exact(MAX_CAP - 9) { - } else { - panic!("isize::MAX + 1 should trigger an overflow!"); - } - } else { - if let Err(AllocError { .. }) = ten_bytes.try_reserve_exact(MAX_CAP - 9) { - } else { - panic!("isize::MAX + 1 should trigger an OOM!") - } - } - if let Err(CapacityOverflow) = ten_bytes.try_reserve_exact(MAX_USIZE) { - } else { - panic!("usize::MAX should trigger an overflow!") - } - } - - { - let mut ten_u32s: Vec<u32> = vec![1, 2, 3, 4, 5, 6, 7, 8, 9, 10]; - - if let Err(CapacityOverflow) = ten_u32s.try_reserve_exact(MAX_CAP / 4 - 10) { - panic!("isize::MAX shouldn't trigger an overflow!"); - } - if let Err(CapacityOverflow) = ten_u32s.try_reserve_exact(MAX_CAP / 4 - 10) { - panic!("isize::MAX shouldn't trigger an overflow!"); - } - if guards_against_isize { - if let Err(CapacityOverflow) = ten_u32s.try_reserve_exact(MAX_CAP / 4 - 9) { - } else { - panic!("isize::MAX + 1 should trigger an overflow!"); - } - } else { - if let Err(AllocError { .. }) = ten_u32s.try_reserve_exact(MAX_CAP / 4 - 9) { - } else { - panic!("isize::MAX + 1 should trigger an OOM!") - } - } - if let Err(CapacityOverflow) = ten_u32s.try_reserve_exact(MAX_USIZE - 20) { - } else { - panic!("usize::MAX should trigger an overflow!") - } - } -} - -#[test] -fn test_stable_pointers() { - /// Pull an element from the iterator, then drop it. - /// Useful to cover both the `next` and `drop` paths of an iterator. - fn next_then_drop<I: Iterator>(mut i: I) { - i.next().unwrap(); - drop(i); - } - - // Test that, if we reserved enough space, adding and removing elements does not - // invalidate references into the vector (such as `v0`). This test also - // runs in Miri, which would detect such problems. - let mut v = Vec::with_capacity(128); - v.push(13); - - // Laundering the lifetime -- we take care that `v` does not reallocate, so that's okay. - let v0 = &mut v[0]; - let v0 = unsafe { &mut *(v0 as *mut _) }; - // Now do a bunch of things and occasionally use `v0` again to assert it is still valid. - - // Pushing/inserting and popping/removing - v.push(1); - v.push(2); - v.insert(1, 1); - assert_eq!(*v0, 13); - v.remove(1); - v.pop().unwrap(); - assert_eq!(*v0, 13); - v.push(1); - v.swap_remove(1); - assert_eq!(v.len(), 2); - v.swap_remove(1); // swap_remove the last element - assert_eq!(*v0, 13); - - // Appending - v.append(&mut vec![27, 19]); - assert_eq!(*v0, 13); - - // Extending - v.extend_from_slice(&[1, 2]); - v.extend(&[1, 2]); // `slice::Iter` (with `T: Copy`) specialization - v.extend(vec![2, 3]); // `vec::IntoIter` specialization - v.extend(std::iter::once(3)); // `TrustedLen` specialization - v.extend(std::iter::empty::<i32>()); // `TrustedLen` specialization with empty iterator - v.extend(std::iter::once(3).filter(|_| true)); // base case - v.extend(std::iter::once(&3)); // `cloned` specialization - assert_eq!(*v0, 13); - - // Truncation - v.truncate(2); - assert_eq!(*v0, 13); - - // Resizing - v.resize_with(v.len() + 10, || 42); - assert_eq!(*v0, 13); - v.resize_with(2, || panic!()); - assert_eq!(*v0, 13); - - // No-op reservation - v.reserve(32); - v.reserve_exact(32); - assert_eq!(*v0, 13); - - // Partial draining - v.resize_with(10, || 42); - next_then_drop(v.drain(5..)); - assert_eq!(*v0, 13); - - // Splicing - v.resize_with(10, || 42); - next_then_drop(v.splice(5.., vec![1, 2, 3, 4, 5])); // empty tail after range - assert_eq!(*v0, 13); - next_then_drop(v.splice(5..8, vec![1])); // replacement is smaller than original range - assert_eq!(*v0, 13); - next_then_drop(v.splice(5..6, vec![1; 10].into_iter().filter(|_| true))); // lower bound not exact - assert_eq!(*v0, 13); - - // Smoke test that would fire even outside Miri if an actual relocation happened. - *v0 -= 13; - assert_eq!(v[0], 0); -} - -// https://github.com/rust-lang/rust/pull/49496 introduced specialization based on: -// -// ``` -// unsafe impl<T: ?Sized> IsZero for *mut T { -// fn is_zero(&self) -> bool { -// (*self).is_null() -// } -// } -// ``` -// -// … to call `RawVec::with_capacity_zeroed` for creating `Vec<*mut T>`, -// which is incorrect for fat pointers since `<*mut T>::is_null` only looks at the data component. -// That is, a fat pointer can be “null” without being made entirely of zero bits. -#[test] -fn vec_macro_repeating_null_raw_fat_pointer() { - let raw_dyn = &mut (|| ()) as &mut dyn Fn() as *mut dyn Fn(); - let vtable = dbg!(ptr_metadata(raw_dyn)); - let null_raw_dyn = ptr_from_raw_parts(std::ptr::null_mut(), vtable); - assert!(null_raw_dyn.is_null()); - - let vec = vec![null_raw_dyn; 1]; - dbg!(ptr_metadata(vec[0])); - assert!(vec[0] == null_raw_dyn); - - // Polyfill for https://github.com/rust-lang/rfcs/pull/2580 - - fn ptr_metadata(ptr: *mut dyn Fn()) -> *mut () { - unsafe { std::mem::transmute::<*mut dyn Fn(), DynRepr>(ptr).vtable } - } - - fn ptr_from_raw_parts(data: *mut (), vtable: *mut ()) -> *mut dyn Fn() { - unsafe { std::mem::transmute::<DynRepr, *mut dyn Fn()>(DynRepr { data, vtable }) } - } - - #[repr(C)] - struct DynRepr { - data: *mut (), - vtable: *mut (), - } -} - -// This test will likely fail if you change the capacities used in -// `RawVec::grow_amortized`. -#[test] -fn test_push_growth_strategy() { - // If the element size is 1, we jump from 0 to 8, then double. - { - let mut v1: Vec<u8> = vec![]; - assert_eq!(v1.capacity(), 0); - - for _ in 0..8 { - v1.push(0); - assert_eq!(v1.capacity(), 8); - } - - for _ in 8..16 { - v1.push(0); - assert_eq!(v1.capacity(), 16); - } - - for _ in 16..32 { - v1.push(0); - assert_eq!(v1.capacity(), 32); - } - - for _ in 32..64 { - v1.push(0); - assert_eq!(v1.capacity(), 64); - } - } - - // If the element size is 2..=1024, we jump from 0 to 4, then double. - { - let mut v2: Vec<u16> = vec![]; - let mut v1024: Vec<[u8; 1024]> = vec![]; - assert_eq!(v2.capacity(), 0); - assert_eq!(v1024.capacity(), 0); - - for _ in 0..4 { - v2.push(0); - v1024.push([0; 1024]); - assert_eq!(v2.capacity(), 4); - assert_eq!(v1024.capacity(), 4); - } - - for _ in 4..8 { - v2.push(0); - v1024.push([0; 1024]); - assert_eq!(v2.capacity(), 8); - assert_eq!(v1024.capacity(), 8); - } - - for _ in 8..16 { - v2.push(0); - v1024.push([0; 1024]); - assert_eq!(v2.capacity(), 16); - assert_eq!(v1024.capacity(), 16); - } - - for _ in 16..32 { - v2.push(0); - v1024.push([0; 1024]); - assert_eq!(v2.capacity(), 32); - assert_eq!(v1024.capacity(), 32); - } - - for _ in 32..64 { - v2.push(0); - v1024.push([0; 1024]); - assert_eq!(v2.capacity(), 64); - assert_eq!(v1024.capacity(), 64); - } - } - - // If the element size is > 1024, we jump from 0 to 1, then double. - { - let mut v1025: Vec<[u8; 1025]> = vec![]; - assert_eq!(v1025.capacity(), 0); - - for _ in 0..1 { - v1025.push([0; 1025]); - assert_eq!(v1025.capacity(), 1); - } - - for _ in 1..2 { - v1025.push([0; 1025]); - assert_eq!(v1025.capacity(), 2); - } - - for _ in 2..4 { - v1025.push([0; 1025]); - assert_eq!(v1025.capacity(), 4); - } - - for _ in 4..8 { - v1025.push([0; 1025]); - assert_eq!(v1025.capacity(), 8); - } - - for _ in 8..16 { - v1025.push([0; 1025]); - assert_eq!(v1025.capacity(), 16); - } - - for _ in 16..32 { - v1025.push([0; 1025]); - assert_eq!(v1025.capacity(), 32); - } - - for _ in 32..64 { - v1025.push([0; 1025]); - assert_eq!(v1025.capacity(), 64); - } - } -} - -macro_rules! generate_assert_eq_vec_and_prim { - ($name:ident<$B:ident>($type:ty)) => { - fn $name<A: PartialEq<$B> + Debug, $B: Debug>(a: Vec<A>, b: $type) { - assert!(a == b); - assert_eq!(a, b); - } - }; -} - -generate_assert_eq_vec_and_prim! { assert_eq_vec_and_slice <B>(&[B]) } -generate_assert_eq_vec_and_prim! { assert_eq_vec_and_array_3<B>([B; 3]) } - -#[test] -fn partialeq_vec_and_prim() { - assert_eq_vec_and_slice(vec![1, 2, 3], &[1, 2, 3]); - assert_eq_vec_and_array_3(vec![1, 2, 3], [1, 2, 3]); -} - -macro_rules! assert_partial_eq_valid { - ($a2:ident, $a3:ident; $b2:ident, $b3: ident) => { - assert!($a2 == $b2); - assert!($a2 != $b3); - assert!($a3 != $b2); - assert!($a3 == $b3); - assert_eq!($a2, $b2); - assert_ne!($a2, $b3); - assert_ne!($a3, $b2); - assert_eq!($a3, $b3); - }; -} - -#[test] -fn partialeq_vec_full() { - let vec2: Vec<_> = vec![1, 2]; - let vec3: Vec<_> = vec![1, 2, 3]; - let slice2: &[_] = &[1, 2]; - let slice3: &[_] = &[1, 2, 3]; - let slicemut2: &[_] = &mut [1, 2]; - let slicemut3: &[_] = &mut [1, 2, 3]; - let array2: [_; 2] = [1, 2]; - let array3: [_; 3] = [1, 2, 3]; - let arrayref2: &[_; 2] = &[1, 2]; - let arrayref3: &[_; 3] = &[1, 2, 3]; - - assert_partial_eq_valid!(vec2,vec3; vec2,vec3); - assert_partial_eq_valid!(vec2,vec3; slice2,slice3); - assert_partial_eq_valid!(vec2,vec3; slicemut2,slicemut3); - assert_partial_eq_valid!(slice2,slice3; vec2,vec3); - assert_partial_eq_valid!(slicemut2,slicemut3; vec2,vec3); - assert_partial_eq_valid!(vec2,vec3; array2,array3); - assert_partial_eq_valid!(vec2,vec3; arrayref2,arrayref3); -} diff --git a/src/liballoc/tests/vec_deque.rs b/src/liballoc/tests/vec_deque.rs deleted file mode 100644 index 762dc4be44d..00000000000 --- a/src/liballoc/tests/vec_deque.rs +++ /dev/null @@ -1,1646 +0,0 @@ -use std::collections::TryReserveError::*; -use std::collections::{vec_deque::Drain, VecDeque}; -use std::fmt::Debug; -use std::mem::size_of; -use std::panic::{catch_unwind, AssertUnwindSafe}; - -use crate::hash; - -use Taggy::*; -use Taggypar::*; - -#[test] -fn test_simple() { - let mut d = VecDeque::new(); - assert_eq!(d.len(), 0); - d.push_front(17); - d.push_front(42); - d.push_back(137); - assert_eq!(d.len(), 3); - d.push_back(137); - assert_eq!(d.len(), 4); - assert_eq!(*d.front().unwrap(), 42); - assert_eq!(*d.back().unwrap(), 137); - let mut i = d.pop_front(); - assert_eq!(i, Some(42)); - i = d.pop_back(); - assert_eq!(i, Some(137)); - i = d.pop_back(); - assert_eq!(i, Some(137)); - i = d.pop_back(); - assert_eq!(i, Some(17)); - assert_eq!(d.len(), 0); - d.push_back(3); - assert_eq!(d.len(), 1); - d.push_front(2); - assert_eq!(d.len(), 2); - d.push_back(4); - assert_eq!(d.len(), 3); - d.push_front(1); - assert_eq!(d.len(), 4); - assert_eq!(d[0], 1); - assert_eq!(d[1], 2); - assert_eq!(d[2], 3); - assert_eq!(d[3], 4); -} - -fn test_parameterized<T: Clone + PartialEq + Debug>(a: T, b: T, c: T, d: T) { - let mut deq = VecDeque::new(); - assert_eq!(deq.len(), 0); - deq.push_front(a.clone()); - deq.push_front(b.clone()); - deq.push_back(c.clone()); - assert_eq!(deq.len(), 3); - deq.push_back(d.clone()); - assert_eq!(deq.len(), 4); - assert_eq!((*deq.front().unwrap()).clone(), b.clone()); - assert_eq!((*deq.back().unwrap()).clone(), d.clone()); - assert_eq!(deq.pop_front().unwrap(), b.clone()); - assert_eq!(deq.pop_back().unwrap(), d.clone()); - assert_eq!(deq.pop_back().unwrap(), c.clone()); - assert_eq!(deq.pop_back().unwrap(), a.clone()); - assert_eq!(deq.len(), 0); - deq.push_back(c.clone()); - assert_eq!(deq.len(), 1); - deq.push_front(b.clone()); - assert_eq!(deq.len(), 2); - deq.push_back(d.clone()); - assert_eq!(deq.len(), 3); - deq.push_front(a.clone()); - assert_eq!(deq.len(), 4); - assert_eq!(deq[0].clone(), a.clone()); - assert_eq!(deq[1].clone(), b.clone()); - assert_eq!(deq[2].clone(), c.clone()); - assert_eq!(deq[3].clone(), d.clone()); -} - -#[test] -fn test_push_front_grow() { - let mut deq = VecDeque::new(); - for i in 0..66 { - deq.push_front(i); - } - assert_eq!(deq.len(), 66); - - for i in 0..66 { - assert_eq!(deq[i], 65 - i); - } - - let mut deq = VecDeque::new(); - for i in 0..66 { - deq.push_back(i); - } - - for i in 0..66 { - assert_eq!(deq[i], i); - } -} - -#[test] -fn test_index() { - let mut deq = VecDeque::new(); - for i in 1..4 { - deq.push_front(i); - } - assert_eq!(deq[1], 2); -} - -#[test] -#[should_panic] -fn test_index_out_of_bounds() { - let mut deq = VecDeque::new(); - for i in 1..4 { - deq.push_front(i); - } - deq[3]; -} - -#[derive(Clone, PartialEq, Debug)] -enum Taggy { - One(i32), - Two(i32, i32), - Three(i32, i32, i32), -} - -#[derive(Clone, PartialEq, Debug)] -enum Taggypar<T> { - Onepar(T), - Twopar(T, T), - Threepar(T, T, T), -} - -#[derive(Clone, PartialEq, Debug)] -struct RecCy { - x: i32, - y: i32, - t: Taggy, -} - -#[test] -fn test_param_int() { - test_parameterized::<i32>(5, 72, 64, 175); -} - -#[test] -fn test_param_taggy() { - test_parameterized::<Taggy>(One(1), Two(1, 2), Three(1, 2, 3), Two(17, 42)); -} - -#[test] -fn test_param_taggypar() { - test_parameterized::<Taggypar<i32>>( - Onepar::<i32>(1), - Twopar::<i32>(1, 2), - Threepar::<i32>(1, 2, 3), - Twopar::<i32>(17, 42), - ); -} - -#[test] -fn test_param_reccy() { - let reccy1 = RecCy { x: 1, y: 2, t: One(1) }; - let reccy2 = RecCy { x: 345, y: 2, t: Two(1, 2) }; - let reccy3 = RecCy { x: 1, y: 777, t: Three(1, 2, 3) }; - let reccy4 = RecCy { x: 19, y: 252, t: Two(17, 42) }; - test_parameterized::<RecCy>(reccy1, reccy2, reccy3, reccy4); -} - -#[test] -fn test_with_capacity() { - let mut d = VecDeque::with_capacity(0); - d.push_back(1); - assert_eq!(d.len(), 1); - let mut d = VecDeque::with_capacity(50); - d.push_back(1); - assert_eq!(d.len(), 1); -} - -#[test] -fn test_with_capacity_non_power_two() { - let mut d3 = VecDeque::with_capacity(3); - d3.push_back(1); - - // X = None, | = lo - // [|1, X, X] - assert_eq!(d3.pop_front(), Some(1)); - // [X, |X, X] - assert_eq!(d3.front(), None); - - // [X, |3, X] - d3.push_back(3); - // [X, |3, 6] - d3.push_back(6); - // [X, X, |6] - assert_eq!(d3.pop_front(), Some(3)); - - // Pushing the lo past half way point to trigger - // the 'B' scenario for growth - // [9, X, |6] - d3.push_back(9); - // [9, 12, |6] - d3.push_back(12); - - d3.push_back(15); - // There used to be a bug here about how the - // VecDeque made growth assumptions about the - // underlying Vec which didn't hold and lead - // to corruption. - // (Vec grows to next power of two) - // good- [9, 12, 15, X, X, X, X, |6] - // bug- [15, 12, X, X, X, |6, X, X] - assert_eq!(d3.pop_front(), Some(6)); - - // Which leads us to the following state which - // would be a failure case. - // bug- [15, 12, X, X, X, X, |X, X] - assert_eq!(d3.front(), Some(&9)); -} - -#[test] -fn test_reserve_exact() { - let mut d = VecDeque::new(); - d.push_back(0); - d.reserve_exact(50); - assert!(d.capacity() >= 51); -} - -#[test] -fn test_reserve() { - let mut d = VecDeque::new(); - d.push_back(0); - d.reserve(50); - assert!(d.capacity() >= 51); -} - -#[test] -fn test_swap() { - let mut d: VecDeque<_> = (0..5).collect(); - d.pop_front(); - d.swap(0, 3); - assert_eq!(d.iter().cloned().collect::<Vec<_>>(), [4, 2, 3, 1]); -} - -#[test] -fn test_iter() { - let mut d = VecDeque::new(); - assert_eq!(d.iter().next(), None); - assert_eq!(d.iter().size_hint(), (0, Some(0))); - - for i in 0..5 { - d.push_back(i); - } - { - let b: &[_] = &[&0, &1, &2, &3, &4]; - assert_eq!(d.iter().collect::<Vec<_>>(), b); - } - - for i in 6..9 { - d.push_front(i); - } - { - let b: &[_] = &[&8, &7, &6, &0, &1, &2, &3, &4]; - assert_eq!(d.iter().collect::<Vec<_>>(), b); - } - - let mut it = d.iter(); - let mut len = d.len(); - loop { - match it.next() { - None => break, - _ => { - len -= 1; - assert_eq!(it.size_hint(), (len, Some(len))) - } - } - } -} - -#[test] -fn test_rev_iter() { - let mut d = VecDeque::new(); - assert_eq!(d.iter().rev().next(), None); - - for i in 0..5 { - d.push_back(i); - } - { - let b: &[_] = &[&4, &3, &2, &1, &0]; - assert_eq!(d.iter().rev().collect::<Vec<_>>(), b); - } - - for i in 6..9 { - d.push_front(i); - } - let b: &[_] = &[&4, &3, &2, &1, &0, &6, &7, &8]; - assert_eq!(d.iter().rev().collect::<Vec<_>>(), b); -} - -#[test] -fn test_mut_rev_iter_wrap() { - let mut d = VecDeque::with_capacity(3); - assert!(d.iter_mut().rev().next().is_none()); - - d.push_back(1); - d.push_back(2); - d.push_back(3); - assert_eq!(d.pop_front(), Some(1)); - d.push_back(4); - - assert_eq!(d.iter_mut().rev().map(|x| *x).collect::<Vec<_>>(), vec![4, 3, 2]); -} - -#[test] -fn test_mut_iter() { - let mut d = VecDeque::new(); - assert!(d.iter_mut().next().is_none()); - - for i in 0..3 { - d.push_front(i); - } - - for (i, elt) in d.iter_mut().enumerate() { - assert_eq!(*elt, 2 - i); - *elt = i; - } - - { - let mut it = d.iter_mut(); - assert_eq!(*it.next().unwrap(), 0); - assert_eq!(*it.next().unwrap(), 1); - assert_eq!(*it.next().unwrap(), 2); - assert!(it.next().is_none()); - } -} - -#[test] -fn test_mut_rev_iter() { - let mut d = VecDeque::new(); - assert!(d.iter_mut().rev().next().is_none()); - - for i in 0..3 { - d.push_front(i); - } - - for (i, elt) in d.iter_mut().rev().enumerate() { - assert_eq!(*elt, i); - *elt = i; - } - - { - let mut it = d.iter_mut().rev(); - assert_eq!(*it.next().unwrap(), 0); - assert_eq!(*it.next().unwrap(), 1); - assert_eq!(*it.next().unwrap(), 2); - assert!(it.next().is_none()); - } -} - -#[test] -fn test_into_iter() { - // Empty iter - { - let d: VecDeque<i32> = VecDeque::new(); - let mut iter = d.into_iter(); - - assert_eq!(iter.size_hint(), (0, Some(0))); - assert_eq!(iter.next(), None); - assert_eq!(iter.size_hint(), (0, Some(0))); - } - - // simple iter - { - let mut d = VecDeque::new(); - for i in 0..5 { - d.push_back(i); - } - - let b = vec![0, 1, 2, 3, 4]; - assert_eq!(d.into_iter().collect::<Vec<_>>(), b); - } - - // wrapped iter - { - let mut d = VecDeque::new(); - for i in 0..5 { - d.push_back(i); - } - for i in 6..9 { - d.push_front(i); - } - - let b = vec![8, 7, 6, 0, 1, 2, 3, 4]; - assert_eq!(d.into_iter().collect::<Vec<_>>(), b); - } - - // partially used - { - let mut d = VecDeque::new(); - for i in 0..5 { - d.push_back(i); - } - for i in 6..9 { - d.push_front(i); - } - - let mut it = d.into_iter(); - assert_eq!(it.size_hint(), (8, Some(8))); - assert_eq!(it.next(), Some(8)); - assert_eq!(it.size_hint(), (7, Some(7))); - assert_eq!(it.next_back(), Some(4)); - assert_eq!(it.size_hint(), (6, Some(6))); - assert_eq!(it.next(), Some(7)); - assert_eq!(it.size_hint(), (5, Some(5))); - } -} - -#[test] -fn test_drain() { - // Empty iter - { - let mut d: VecDeque<i32> = VecDeque::new(); - - { - let mut iter = d.drain(..); - - assert_eq!(iter.size_hint(), (0, Some(0))); - assert_eq!(iter.next(), None); - assert_eq!(iter.size_hint(), (0, Some(0))); - } - - assert!(d.is_empty()); - } - - // simple iter - { - let mut d = VecDeque::new(); - for i in 0..5 { - d.push_back(i); - } - - assert_eq!(d.drain(..).collect::<Vec<_>>(), [0, 1, 2, 3, 4]); - assert!(d.is_empty()); - } - - // wrapped iter - { - let mut d = VecDeque::new(); - for i in 0..5 { - d.push_back(i); - } - for i in 6..9 { - d.push_front(i); - } - - assert_eq!(d.drain(..).collect::<Vec<_>>(), [8, 7, 6, 0, 1, 2, 3, 4]); - assert!(d.is_empty()); - } - - // partially used - { - let mut d: VecDeque<_> = VecDeque::new(); - for i in 0..5 { - d.push_back(i); - } - for i in 6..9 { - d.push_front(i); - } - - { - let mut it = d.drain(..); - assert_eq!(it.size_hint(), (8, Some(8))); - assert_eq!(it.next(), Some(8)); - assert_eq!(it.size_hint(), (7, Some(7))); - assert_eq!(it.next_back(), Some(4)); - assert_eq!(it.size_hint(), (6, Some(6))); - assert_eq!(it.next(), Some(7)); - assert_eq!(it.size_hint(), (5, Some(5))); - } - assert!(d.is_empty()); - } -} - -#[test] -fn test_from_iter() { - let v = vec![1, 2, 3, 4, 5, 6, 7]; - let deq: VecDeque<_> = v.iter().cloned().collect(); - let u: Vec<_> = deq.iter().cloned().collect(); - assert_eq!(u, v); - - let seq = (0..).step_by(2).take(256); - let deq: VecDeque<_> = seq.collect(); - for (i, &x) in deq.iter().enumerate() { - assert_eq!(2 * i, x); - } - assert_eq!(deq.len(), 256); -} - -#[test] -fn test_clone() { - let mut d = VecDeque::new(); - d.push_front(17); - d.push_front(42); - d.push_back(137); - d.push_back(137); - assert_eq!(d.len(), 4); - let mut e = d.clone(); - assert_eq!(e.len(), 4); - while !d.is_empty() { - assert_eq!(d.pop_back(), e.pop_back()); - } - assert_eq!(d.len(), 0); - assert_eq!(e.len(), 0); -} - -#[test] -fn test_eq() { - let mut d = VecDeque::new(); - assert!(d == VecDeque::with_capacity(0)); - d.push_front(137); - d.push_front(17); - d.push_front(42); - d.push_back(137); - let mut e = VecDeque::with_capacity(0); - e.push_back(42); - e.push_back(17); - e.push_back(137); - e.push_back(137); - assert!(&e == &d); - e.pop_back(); - e.push_back(0); - assert!(e != d); - e.clear(); - assert!(e == VecDeque::new()); -} - -#[test] -fn test_partial_eq_array() { - let d = VecDeque::<char>::new(); - assert!(d == []); - - let mut d = VecDeque::new(); - d.push_front('a'); - assert!(d == ['a']); - - let mut d = VecDeque::new(); - d.push_back('a'); - assert!(d == ['a']); - - let mut d = VecDeque::new(); - d.push_back('a'); - d.push_back('b'); - assert!(d == ['a', 'b']); -} - -#[test] -fn test_hash() { - let mut x = VecDeque::new(); - let mut y = VecDeque::new(); - - x.push_back(1); - x.push_back(2); - x.push_back(3); - - y.push_back(0); - y.push_back(1); - y.pop_front(); - y.push_back(2); - y.push_back(3); - - assert!(hash(&x) == hash(&y)); -} - -#[test] -fn test_hash_after_rotation() { - // test that two deques hash equal even if elements are laid out differently - let len = 28; - let mut ring: VecDeque<i32> = (0..len as i32).collect(); - let orig = ring.clone(); - for _ in 0..ring.capacity() { - // shift values 1 step to the right by pop, sub one, push - ring.pop_front(); - for elt in &mut ring { - *elt -= 1; - } - ring.push_back(len - 1); - assert_eq!(hash(&orig), hash(&ring)); - assert_eq!(orig, ring); - assert_eq!(ring, orig); - } -} - -#[test] -fn test_eq_after_rotation() { - // test that two deques are equal even if elements are laid out differently - let len = 28; - let mut ring: VecDeque<i32> = (0..len as i32).collect(); - let mut shifted = ring.clone(); - for _ in 0..10 { - // shift values 1 step to the right by pop, sub one, push - ring.pop_front(); - for elt in &mut ring { - *elt -= 1; - } - ring.push_back(len - 1); - } - - // try every shift - for _ in 0..shifted.capacity() { - shifted.pop_front(); - for elt in &mut shifted { - *elt -= 1; - } - shifted.push_back(len - 1); - assert_eq!(shifted, ring); - assert_eq!(ring, shifted); - } -} - -#[test] -fn test_ord() { - let x = VecDeque::new(); - let mut y = VecDeque::new(); - y.push_back(1); - y.push_back(2); - y.push_back(3); - assert!(x < y); - assert!(y > x); - assert!(x <= x); - assert!(x >= x); -} - -#[test] -fn test_show() { - let ringbuf: VecDeque<_> = (0..10).collect(); - assert_eq!(format!("{:?}", ringbuf), "[0, 1, 2, 3, 4, 5, 6, 7, 8, 9]"); - - let ringbuf: VecDeque<_> = vec!["just", "one", "test", "more"].iter().cloned().collect(); - assert_eq!(format!("{:?}", ringbuf), "[\"just\", \"one\", \"test\", \"more\"]"); -} - -#[test] -fn test_drop() { - static mut DROPS: i32 = 0; - struct Elem; - impl Drop for Elem { - fn drop(&mut self) { - unsafe { - DROPS += 1; - } - } - } - - let mut ring = VecDeque::new(); - ring.push_back(Elem); - ring.push_front(Elem); - ring.push_back(Elem); - ring.push_front(Elem); - drop(ring); - - assert_eq!(unsafe { DROPS }, 4); -} - -#[test] -fn test_drop_with_pop() { - static mut DROPS: i32 = 0; - struct Elem; - impl Drop for Elem { - fn drop(&mut self) { - unsafe { - DROPS += 1; - } - } - } - - let mut ring = VecDeque::new(); - ring.push_back(Elem); - ring.push_front(Elem); - ring.push_back(Elem); - ring.push_front(Elem); - - drop(ring.pop_back()); - drop(ring.pop_front()); - assert_eq!(unsafe { DROPS }, 2); - - drop(ring); - assert_eq!(unsafe { DROPS }, 4); -} - -#[test] -fn test_drop_clear() { - static mut DROPS: i32 = 0; - struct Elem; - impl Drop for Elem { - fn drop(&mut self) { - unsafe { - DROPS += 1; - } - } - } - - let mut ring = VecDeque::new(); - ring.push_back(Elem); - ring.push_front(Elem); - ring.push_back(Elem); - ring.push_front(Elem); - ring.clear(); - assert_eq!(unsafe { DROPS }, 4); - - drop(ring); - assert_eq!(unsafe { DROPS }, 4); -} - -#[test] -fn test_drop_panic() { - static mut DROPS: i32 = 0; - - struct D(bool); - - impl Drop for D { - fn drop(&mut self) { - unsafe { - DROPS += 1; - } - - if self.0 { - panic!("panic in `drop`"); - } - } - } - - let mut q = VecDeque::new(); - q.push_back(D(false)); - q.push_back(D(false)); - q.push_back(D(false)); - q.push_back(D(false)); - q.push_back(D(false)); - q.push_front(D(false)); - q.push_front(D(false)); - q.push_front(D(true)); - - catch_unwind(move || drop(q)).ok(); - - assert_eq!(unsafe { DROPS }, 8); -} - -#[test] -fn test_reserve_grow() { - // test growth path A - // [T o o H] -> [T o o H . . . . ] - let mut ring = VecDeque::with_capacity(4); - for i in 0..3 { - ring.push_back(i); - } - ring.reserve(7); - for i in 0..3 { - assert_eq!(ring.pop_front(), Some(i)); - } - - // test growth path B - // [H T o o] -> [. T o o H . . . ] - let mut ring = VecDeque::with_capacity(4); - for i in 0..1 { - ring.push_back(i); - assert_eq!(ring.pop_front(), Some(i)); - } - for i in 0..3 { - ring.push_back(i); - } - ring.reserve(7); - for i in 0..3 { - assert_eq!(ring.pop_front(), Some(i)); - } - - // test growth path C - // [o o H T] -> [o o H . . . . T ] - let mut ring = VecDeque::with_capacity(4); - for i in 0..3 { - ring.push_back(i); - assert_eq!(ring.pop_front(), Some(i)); - } - for i in 0..3 { - ring.push_back(i); - } - ring.reserve(7); - for i in 0..3 { - assert_eq!(ring.pop_front(), Some(i)); - } -} - -#[test] -fn test_get() { - let mut ring = VecDeque::new(); - ring.push_back(0); - assert_eq!(ring.get(0), Some(&0)); - assert_eq!(ring.get(1), None); - - ring.push_back(1); - assert_eq!(ring.get(0), Some(&0)); - assert_eq!(ring.get(1), Some(&1)); - assert_eq!(ring.get(2), None); - - ring.push_back(2); - assert_eq!(ring.get(0), Some(&0)); - assert_eq!(ring.get(1), Some(&1)); - assert_eq!(ring.get(2), Some(&2)); - assert_eq!(ring.get(3), None); - - assert_eq!(ring.pop_front(), Some(0)); - assert_eq!(ring.get(0), Some(&1)); - assert_eq!(ring.get(1), Some(&2)); - assert_eq!(ring.get(2), None); - - assert_eq!(ring.pop_front(), Some(1)); - assert_eq!(ring.get(0), Some(&2)); - assert_eq!(ring.get(1), None); - - assert_eq!(ring.pop_front(), Some(2)); - assert_eq!(ring.get(0), None); - assert_eq!(ring.get(1), None); -} - -#[test] -fn test_get_mut() { - let mut ring = VecDeque::new(); - for i in 0..3 { - ring.push_back(i); - } - - match ring.get_mut(1) { - Some(x) => *x = -1, - None => (), - }; - - assert_eq!(ring.get_mut(0), Some(&mut 0)); - assert_eq!(ring.get_mut(1), Some(&mut -1)); - assert_eq!(ring.get_mut(2), Some(&mut 2)); - assert_eq!(ring.get_mut(3), None); - - assert_eq!(ring.pop_front(), Some(0)); - assert_eq!(ring.get_mut(0), Some(&mut -1)); - assert_eq!(ring.get_mut(1), Some(&mut 2)); - assert_eq!(ring.get_mut(2), None); -} - -#[test] -fn test_front() { - let mut ring = VecDeque::new(); - ring.push_back(10); - ring.push_back(20); - assert_eq!(ring.front(), Some(&10)); - ring.pop_front(); - assert_eq!(ring.front(), Some(&20)); - ring.pop_front(); - assert_eq!(ring.front(), None); -} - -#[test] -fn test_as_slices() { - let mut ring: VecDeque<i32> = VecDeque::with_capacity(127); - let cap = ring.capacity() as i32; - let first = cap / 2; - let last = cap - first; - for i in 0..first { - ring.push_back(i); - - let (left, right) = ring.as_slices(); - let expected: Vec<_> = (0..=i).collect(); - assert_eq!(left, &expected[..]); - assert_eq!(right, []); - } - - for j in -last..0 { - ring.push_front(j); - let (left, right) = ring.as_slices(); - let expected_left: Vec<_> = (-last..=j).rev().collect(); - let expected_right: Vec<_> = (0..first).collect(); - assert_eq!(left, &expected_left[..]); - assert_eq!(right, &expected_right[..]); - } - - assert_eq!(ring.len() as i32, cap); - assert_eq!(ring.capacity() as i32, cap); -} - -#[test] -fn test_as_mut_slices() { - let mut ring: VecDeque<i32> = VecDeque::with_capacity(127); - let cap = ring.capacity() as i32; - let first = cap / 2; - let last = cap - first; - for i in 0..first { - ring.push_back(i); - - let (left, right) = ring.as_mut_slices(); - let expected: Vec<_> = (0..=i).collect(); - assert_eq!(left, &expected[..]); - assert_eq!(right, []); - } - - for j in -last..0 { - ring.push_front(j); - let (left, right) = ring.as_mut_slices(); - let expected_left: Vec<_> = (-last..=j).rev().collect(); - let expected_right: Vec<_> = (0..first).collect(); - assert_eq!(left, &expected_left[..]); - assert_eq!(right, &expected_right[..]); - } - - assert_eq!(ring.len() as i32, cap); - assert_eq!(ring.capacity() as i32, cap); -} - -#[test] -fn test_append() { - let mut a: VecDeque<_> = vec![1, 2, 3].into_iter().collect(); - let mut b: VecDeque<_> = vec![4, 5, 6].into_iter().collect(); - - // normal append - a.append(&mut b); - assert_eq!(a.iter().cloned().collect::<Vec<_>>(), [1, 2, 3, 4, 5, 6]); - assert_eq!(b.iter().cloned().collect::<Vec<_>>(), []); - - // append nothing to something - a.append(&mut b); - assert_eq!(a.iter().cloned().collect::<Vec<_>>(), [1, 2, 3, 4, 5, 6]); - assert_eq!(b.iter().cloned().collect::<Vec<_>>(), []); - - // append something to nothing - b.append(&mut a); - assert_eq!(b.iter().cloned().collect::<Vec<_>>(), [1, 2, 3, 4, 5, 6]); - assert_eq!(a.iter().cloned().collect::<Vec<_>>(), []); -} - -#[test] -fn test_append_permutations() { - fn construct_vec_deque( - push_back: usize, - pop_back: usize, - push_front: usize, - pop_front: usize, - ) -> VecDeque<usize> { - let mut out = VecDeque::new(); - for a in 0..push_back { - out.push_back(a); - } - for b in 0..push_front { - out.push_front(push_back + b); - } - for _ in 0..pop_back { - out.pop_back(); - } - for _ in 0..pop_front { - out.pop_front(); - } - out - } - - // Miri is too slow - let max = if cfg!(miri) { 3 } else { 5 }; - - // Many different permutations of both the `VecDeque` getting appended to - // and the one getting appended are generated to check `append`. - // This ensures all 6 code paths of `append` are tested. - for src_push_back in 0..max { - for src_push_front in 0..max { - // doesn't pop more values than are pushed - for src_pop_back in 0..(src_push_back + src_push_front) { - for src_pop_front in 0..(src_push_back + src_push_front - src_pop_back) { - let src = construct_vec_deque( - src_push_back, - src_pop_back, - src_push_front, - src_pop_front, - ); - - for dst_push_back in 0..max { - for dst_push_front in 0..max { - for dst_pop_back in 0..(dst_push_back + dst_push_front) { - for dst_pop_front in - 0..(dst_push_back + dst_push_front - dst_pop_back) - { - let mut dst = construct_vec_deque( - dst_push_back, - dst_pop_back, - dst_push_front, - dst_pop_front, - ); - let mut src = src.clone(); - - // Assert that appending `src` to `dst` gives the same order - // of values as iterating over both in sequence. - let correct = dst - .iter() - .chain(src.iter()) - .cloned() - .collect::<Vec<usize>>(); - dst.append(&mut src); - assert_eq!(dst, correct); - assert!(src.is_empty()); - } - } - } - } - } - } - } - } -} - -struct DropCounter<'a> { - count: &'a mut u32, -} - -impl Drop for DropCounter<'_> { - fn drop(&mut self) { - *self.count += 1; - } -} - -#[test] -fn test_append_double_drop() { - let (mut count_a, mut count_b) = (0, 0); - { - let mut a = VecDeque::new(); - let mut b = VecDeque::new(); - a.push_back(DropCounter { count: &mut count_a }); - b.push_back(DropCounter { count: &mut count_b }); - - a.append(&mut b); - } - assert_eq!(count_a, 1); - assert_eq!(count_b, 1); -} - -#[test] -fn test_retain() { - let mut buf = VecDeque::new(); - buf.extend(1..5); - buf.retain(|&x| x % 2 == 0); - let v: Vec<_> = buf.into_iter().collect(); - assert_eq!(&v[..], &[2, 4]); -} - -#[test] -fn test_extend_ref() { - let mut v = VecDeque::new(); - v.push_back(1); - v.extend(&[2, 3, 4]); - - assert_eq!(v.len(), 4); - assert_eq!(v[0], 1); - assert_eq!(v[1], 2); - assert_eq!(v[2], 3); - assert_eq!(v[3], 4); - - let mut w = VecDeque::new(); - w.push_back(5); - w.push_back(6); - v.extend(&w); - - assert_eq!(v.len(), 6); - assert_eq!(v[0], 1); - assert_eq!(v[1], 2); - assert_eq!(v[2], 3); - assert_eq!(v[3], 4); - assert_eq!(v[4], 5); - assert_eq!(v[5], 6); -} - -#[test] -fn test_contains() { - let mut v = VecDeque::new(); - v.extend(&[2, 3, 4]); - - assert!(v.contains(&3)); - assert!(!v.contains(&1)); - - v.clear(); - - assert!(!v.contains(&3)); -} - -#[allow(dead_code)] -fn assert_covariance() { - fn drain<'new>(d: Drain<'static, &'static str>) -> Drain<'new, &'new str> { - d - } -} - -#[test] -fn test_is_empty() { - let mut v = VecDeque::<i32>::new(); - assert!(v.is_empty()); - assert!(v.iter().is_empty()); - assert!(v.iter_mut().is_empty()); - v.extend(&[2, 3, 4]); - assert!(!v.is_empty()); - assert!(!v.iter().is_empty()); - assert!(!v.iter_mut().is_empty()); - while let Some(_) = v.pop_front() { - assert_eq!(v.is_empty(), v.len() == 0); - assert_eq!(v.iter().is_empty(), v.iter().len() == 0); - assert_eq!(v.iter_mut().is_empty(), v.iter_mut().len() == 0); - } - assert!(v.is_empty()); - assert!(v.iter().is_empty()); - assert!(v.iter_mut().is_empty()); - assert!(v.into_iter().is_empty()); -} - -#[test] -fn test_reserve_exact_2() { - // This is all the same as test_reserve - - let mut v = VecDeque::new(); - - v.reserve_exact(2); - assert!(v.capacity() >= 2); - - for i in 0..16 { - v.push_back(i); - } - - assert!(v.capacity() >= 16); - v.reserve_exact(16); - assert!(v.capacity() >= 32); - - v.push_back(16); - - v.reserve_exact(16); - assert!(v.capacity() >= 48) -} - -#[test] -#[cfg_attr(miri, ignore)] // Miri does not support signalling OOM -#[cfg_attr(target_os = "android", ignore)] // Android used in CI has a broken dlmalloc -fn test_try_reserve() { - // These are the interesting cases: - // * exactly isize::MAX should never trigger a CapacityOverflow (can be OOM) - // * > isize::MAX should always fail - // * On 16/32-bit should CapacityOverflow - // * On 64-bit should OOM - // * overflow may trigger when adding `len` to `cap` (in number of elements) - // * overflow may trigger when multiplying `new_cap` by size_of::<T> (to get bytes) - - const MAX_CAP: usize = (isize::MAX as usize + 1) / 2 - 1; - const MAX_USIZE: usize = usize::MAX; - - // On 16/32-bit, we check that allocations don't exceed isize::MAX, - // on 64-bit, we assume the OS will give an OOM for such a ridiculous size. - // Any platform that succeeds for these requests is technically broken with - // ptr::offset because LLVM is the worst. - let guards_against_isize = size_of::<usize>() < 8; - - { - // Note: basic stuff is checked by test_reserve - let mut empty_bytes: VecDeque<u8> = VecDeque::new(); - - // Check isize::MAX doesn't count as an overflow - if let Err(CapacityOverflow) = empty_bytes.try_reserve(MAX_CAP) { - panic!("isize::MAX shouldn't trigger an overflow!"); - } - // Play it again, frank! (just to be sure) - if let Err(CapacityOverflow) = empty_bytes.try_reserve(MAX_CAP) { - panic!("isize::MAX shouldn't trigger an overflow!"); - } - - if guards_against_isize { - // Check isize::MAX + 1 does count as overflow - if let Err(CapacityOverflow) = empty_bytes.try_reserve(MAX_CAP + 1) { - } else { - panic!("isize::MAX + 1 should trigger an overflow!") - } - - // Check usize::MAX does count as overflow - if let Err(CapacityOverflow) = empty_bytes.try_reserve(MAX_USIZE) { - } else { - panic!("usize::MAX should trigger an overflow!") - } - } else { - // Check isize::MAX is an OOM - // VecDeque starts with capacity 7, always adds 1 to the capacity - // and also rounds the number to next power of 2 so this is the - // furthest we can go without triggering CapacityOverflow - if let Err(AllocError { .. }) = empty_bytes.try_reserve(MAX_CAP) { - } else { - panic!("isize::MAX + 1 should trigger an OOM!") - } - } - } - - { - // Same basic idea, but with non-zero len - let mut ten_bytes: VecDeque<u8> = vec![1, 2, 3, 4, 5, 6, 7, 8, 9, 10].into_iter().collect(); - - if let Err(CapacityOverflow) = ten_bytes.try_reserve(MAX_CAP - 10) { - panic!("isize::MAX shouldn't trigger an overflow!"); - } - if let Err(CapacityOverflow) = ten_bytes.try_reserve(MAX_CAP - 10) { - panic!("isize::MAX shouldn't trigger an overflow!"); - } - if guards_against_isize { - if let Err(CapacityOverflow) = ten_bytes.try_reserve(MAX_CAP - 9) { - } else { - panic!("isize::MAX + 1 should trigger an overflow!"); - } - } else { - if let Err(AllocError { .. }) = ten_bytes.try_reserve(MAX_CAP - 9) { - } else { - panic!("isize::MAX + 1 should trigger an OOM!") - } - } - // Should always overflow in the add-to-len - if let Err(CapacityOverflow) = ten_bytes.try_reserve(MAX_USIZE) { - } else { - panic!("usize::MAX should trigger an overflow!") - } - } - - { - // Same basic idea, but with interesting type size - let mut ten_u32s: VecDeque<u32> = vec![1, 2, 3, 4, 5, 6, 7, 8, 9, 10].into_iter().collect(); - - if let Err(CapacityOverflow) = ten_u32s.try_reserve(MAX_CAP / 4 - 10) { - panic!("isize::MAX shouldn't trigger an overflow!"); - } - if let Err(CapacityOverflow) = ten_u32s.try_reserve(MAX_CAP / 4 - 10) { - panic!("isize::MAX shouldn't trigger an overflow!"); - } - if guards_against_isize { - if let Err(CapacityOverflow) = ten_u32s.try_reserve(MAX_CAP / 4 - 9) { - } else { - panic!("isize::MAX + 1 should trigger an overflow!"); - } - } else { - if let Err(AllocError { .. }) = ten_u32s.try_reserve(MAX_CAP / 4 - 9) { - } else { - panic!("isize::MAX + 1 should trigger an OOM!") - } - } - // Should fail in the mul-by-size - if let Err(CapacityOverflow) = ten_u32s.try_reserve(MAX_USIZE - 20) { - } else { - panic!("usize::MAX should trigger an overflow!"); - } - } -} - -#[test] -#[cfg_attr(miri, ignore)] // Miri does not support signalling OOM -#[cfg_attr(target_os = "android", ignore)] // Android used in CI has a broken dlmalloc -fn test_try_reserve_exact() { - // This is exactly the same as test_try_reserve with the method changed. - // See that test for comments. - - const MAX_CAP: usize = (isize::MAX as usize + 1) / 2 - 1; - const MAX_USIZE: usize = usize::MAX; - - let guards_against_isize = size_of::<usize>() < 8; - - { - let mut empty_bytes: VecDeque<u8> = VecDeque::new(); - - if let Err(CapacityOverflow) = empty_bytes.try_reserve_exact(MAX_CAP) { - panic!("isize::MAX shouldn't trigger an overflow!"); - } - if let Err(CapacityOverflow) = empty_bytes.try_reserve_exact(MAX_CAP) { - panic!("isize::MAX shouldn't trigger an overflow!"); - } - - if guards_against_isize { - if let Err(CapacityOverflow) = empty_bytes.try_reserve_exact(MAX_CAP + 1) { - } else { - panic!("isize::MAX + 1 should trigger an overflow!") - } - - if let Err(CapacityOverflow) = empty_bytes.try_reserve_exact(MAX_USIZE) { - } else { - panic!("usize::MAX should trigger an overflow!") - } - } else { - // Check isize::MAX is an OOM - // VecDeque starts with capacity 7, always adds 1 to the capacity - // and also rounds the number to next power of 2 so this is the - // furthest we can go without triggering CapacityOverflow - if let Err(AllocError { .. }) = empty_bytes.try_reserve_exact(MAX_CAP) { - } else { - panic!("isize::MAX + 1 should trigger an OOM!") - } - } - } - - { - let mut ten_bytes: VecDeque<u8> = vec![1, 2, 3, 4, 5, 6, 7, 8, 9, 10].into_iter().collect(); - - if let Err(CapacityOverflow) = ten_bytes.try_reserve_exact(MAX_CAP - 10) { - panic!("isize::MAX shouldn't trigger an overflow!"); - } - if let Err(CapacityOverflow) = ten_bytes.try_reserve_exact(MAX_CAP - 10) { - panic!("isize::MAX shouldn't trigger an overflow!"); - } - if guards_against_isize { - if let Err(CapacityOverflow) = ten_bytes.try_reserve_exact(MAX_CAP - 9) { - } else { - panic!("isize::MAX + 1 should trigger an overflow!"); - } - } else { - if let Err(AllocError { .. }) = ten_bytes.try_reserve_exact(MAX_CAP - 9) { - } else { - panic!("isize::MAX + 1 should trigger an OOM!") - } - } - if let Err(CapacityOverflow) = ten_bytes.try_reserve_exact(MAX_USIZE) { - } else { - panic!("usize::MAX should trigger an overflow!") - } - } - - { - let mut ten_u32s: VecDeque<u32> = vec![1, 2, 3, 4, 5, 6, 7, 8, 9, 10].into_iter().collect(); - - if let Err(CapacityOverflow) = ten_u32s.try_reserve_exact(MAX_CAP / 4 - 10) { - panic!("isize::MAX shouldn't trigger an overflow!"); - } - if let Err(CapacityOverflow) = ten_u32s.try_reserve_exact(MAX_CAP / 4 - 10) { - panic!("isize::MAX shouldn't trigger an overflow!"); - } - if guards_against_isize { - if let Err(CapacityOverflow) = ten_u32s.try_reserve_exact(MAX_CAP / 4 - 9) { - } else { - panic!("isize::MAX + 1 should trigger an overflow!"); - } - } else { - if let Err(AllocError { .. }) = ten_u32s.try_reserve_exact(MAX_CAP / 4 - 9) { - } else { - panic!("isize::MAX + 1 should trigger an OOM!") - } - } - if let Err(CapacityOverflow) = ten_u32s.try_reserve_exact(MAX_USIZE - 20) { - } else { - panic!("usize::MAX should trigger an overflow!") - } - } -} - -#[test] -fn test_rotate_nop() { - let mut v: VecDeque<_> = (0..10).collect(); - assert_unchanged(&v); - - v.rotate_left(0); - assert_unchanged(&v); - - v.rotate_left(10); - assert_unchanged(&v); - - v.rotate_right(0); - assert_unchanged(&v); - - v.rotate_right(10); - assert_unchanged(&v); - - v.rotate_left(3); - v.rotate_right(3); - assert_unchanged(&v); - - v.rotate_right(3); - v.rotate_left(3); - assert_unchanged(&v); - - v.rotate_left(6); - v.rotate_right(6); - assert_unchanged(&v); - - v.rotate_right(6); - v.rotate_left(6); - assert_unchanged(&v); - - v.rotate_left(3); - v.rotate_left(7); - assert_unchanged(&v); - - v.rotate_right(4); - v.rotate_right(6); - assert_unchanged(&v); - - v.rotate_left(1); - v.rotate_left(2); - v.rotate_left(3); - v.rotate_left(4); - assert_unchanged(&v); - - v.rotate_right(1); - v.rotate_right(2); - v.rotate_right(3); - v.rotate_right(4); - assert_unchanged(&v); - - fn assert_unchanged(v: &VecDeque<i32>) { - assert_eq!(v, &[0, 1, 2, 3, 4, 5, 6, 7, 8, 9]); - } -} - -#[test] -fn test_rotate_left_parts() { - let mut v: VecDeque<_> = (1..=7).collect(); - v.rotate_left(2); - assert_eq!(v.as_slices(), (&[3, 4, 5, 6, 7, 1][..], &[2][..])); - v.rotate_left(2); - assert_eq!(v.as_slices(), (&[5, 6, 7, 1][..], &[2, 3, 4][..])); - v.rotate_left(2); - assert_eq!(v.as_slices(), (&[7, 1][..], &[2, 3, 4, 5, 6][..])); - v.rotate_left(2); - assert_eq!(v.as_slices(), (&[2, 3, 4, 5, 6, 7, 1][..], &[][..])); - v.rotate_left(2); - assert_eq!(v.as_slices(), (&[4, 5, 6, 7, 1, 2][..], &[3][..])); - v.rotate_left(2); - assert_eq!(v.as_slices(), (&[6, 7, 1, 2][..], &[3, 4, 5][..])); - v.rotate_left(2); - assert_eq!(v.as_slices(), (&[1, 2][..], &[3, 4, 5, 6, 7][..])); -} - -#[test] -fn test_rotate_right_parts() { - let mut v: VecDeque<_> = (1..=7).collect(); - v.rotate_right(2); - assert_eq!(v.as_slices(), (&[6, 7][..], &[1, 2, 3, 4, 5][..])); - v.rotate_right(2); - assert_eq!(v.as_slices(), (&[4, 5, 6, 7][..], &[1, 2, 3][..])); - v.rotate_right(2); - assert_eq!(v.as_slices(), (&[2, 3, 4, 5, 6, 7][..], &[1][..])); - v.rotate_right(2); - assert_eq!(v.as_slices(), (&[7, 1, 2, 3, 4, 5, 6][..], &[][..])); - v.rotate_right(2); - assert_eq!(v.as_slices(), (&[5, 6][..], &[7, 1, 2, 3, 4][..])); - v.rotate_right(2); - assert_eq!(v.as_slices(), (&[3, 4, 5, 6][..], &[7, 1, 2][..])); - v.rotate_right(2); - assert_eq!(v.as_slices(), (&[1, 2, 3, 4, 5, 6][..], &[7][..])); -} - -#[test] -fn test_rotate_left_random() { - let shifts = [ - 6, 1, 0, 11, 12, 1, 11, 7, 9, 3, 6, 1, 4, 0, 5, 1, 3, 1, 12, 8, 3, 1, 11, 11, 9, 4, 12, 3, - 12, 9, 11, 1, 7, 9, 7, 2, - ]; - let n = 12; - let mut v: VecDeque<_> = (0..n).collect(); - let mut total_shift = 0; - for shift in shifts.iter().cloned() { - v.rotate_left(shift); - total_shift += shift; - for i in 0..n { - assert_eq!(v[i], (i + total_shift) % n); - } - } -} - -#[test] -fn test_rotate_right_random() { - let shifts = [ - 6, 1, 0, 11, 12, 1, 11, 7, 9, 3, 6, 1, 4, 0, 5, 1, 3, 1, 12, 8, 3, 1, 11, 11, 9, 4, 12, 3, - 12, 9, 11, 1, 7, 9, 7, 2, - ]; - let n = 12; - let mut v: VecDeque<_> = (0..n).collect(); - let mut total_shift = 0; - for shift in shifts.iter().cloned() { - v.rotate_right(shift); - total_shift += shift; - for i in 0..n { - assert_eq!(v[(i + total_shift) % n], i); - } - } -} - -#[test] -fn test_try_fold_empty() { - assert_eq!(Some(0), VecDeque::<u32>::new().iter().try_fold(0, |_, _| None)); -} - -#[test] -fn test_try_fold_none() { - let v: VecDeque<u32> = (0..12).collect(); - assert_eq!(None, v.into_iter().try_fold(0, |a, b| if b < 11 { Some(a + b) } else { None })); -} - -#[test] -fn test_try_fold_ok() { - let v: VecDeque<u32> = (0..12).collect(); - assert_eq!(Ok::<_, ()>(66), v.into_iter().try_fold(0, |a, b| Ok(a + b))); -} - -#[test] -fn test_try_fold_unit() { - let v: VecDeque<()> = std::iter::repeat(()).take(42).collect(); - assert_eq!(Some(()), v.into_iter().try_fold((), |(), ()| Some(()))); -} - -#[test] -fn test_try_fold_unit_none() { - let v: std::collections::VecDeque<()> = [(); 10].iter().cloned().collect(); - let mut iter = v.into_iter(); - assert!(iter.try_fold((), |_, _| None).is_none()); - assert_eq!(iter.len(), 9); -} - -#[test] -fn test_try_fold_rotated() { - let mut v: VecDeque<_> = (0..12).collect(); - for n in 0..10 { - if n & 1 == 0 { - v.rotate_left(n); - } else { - v.rotate_right(n); - } - assert_eq!(Ok::<_, ()>(66), v.iter().try_fold(0, |a, b| Ok(a + b))); - } -} - -#[test] -fn test_try_fold_moves_iter() { - let v: VecDeque<_> = [10, 20, 30, 40, 100, 60, 70, 80, 90].iter().collect(); - let mut iter = v.into_iter(); - assert_eq!(iter.try_fold(0_i8, |acc, &x| acc.checked_add(x)), None); - assert_eq!(iter.next(), Some(&60)); -} - -#[test] -fn test_try_fold_exhaust_wrap() { - let mut v = VecDeque::with_capacity(7); - v.push_back(1); - v.push_back(1); - v.push_back(1); - v.pop_front(); - v.pop_front(); - let mut iter = v.iter(); - let _ = iter.try_fold(0, |_, _| Some(1)); - assert!(iter.is_empty()); -} - -#[test] -fn test_try_fold_wraparound() { - let mut v = VecDeque::with_capacity(8); - v.push_back(7); - v.push_back(8); - v.push_back(9); - v.push_front(2); - v.push_front(1); - let mut iter = v.iter(); - let _ = iter.find(|&&x| x == 2); - assert_eq!(Some(&7), iter.next()); -} - -#[test] -fn test_try_rfold_rotated() { - let mut v: VecDeque<_> = (0..12).collect(); - for n in 0..10 { - if n & 1 == 0 { - v.rotate_left(n); - } else { - v.rotate_right(n); - } - assert_eq!(Ok::<_, ()>(66), v.iter().try_rfold(0, |a, b| Ok(a + b))); - } -} - -#[test] -fn test_try_rfold_moves_iter() { - let v: VecDeque<_> = [10, 20, 30, 40, 100, 60, 70, 80, 90].iter().collect(); - let mut iter = v.into_iter(); - assert_eq!(iter.try_rfold(0_i8, |acc, &x| acc.checked_add(x)), None); - assert_eq!(iter.next_back(), Some(&70)); -} - -#[test] -fn truncate_leak() { - static mut DROPS: i32 = 0; - - struct D(bool); - - impl Drop for D { - fn drop(&mut self) { - unsafe { - DROPS += 1; - } - - if self.0 { - panic!("panic in `drop`"); - } - } - } - - let mut q = VecDeque::new(); - q.push_back(D(false)); - q.push_back(D(false)); - q.push_back(D(false)); - q.push_back(D(false)); - q.push_back(D(false)); - q.push_front(D(true)); - q.push_front(D(false)); - q.push_front(D(false)); - - catch_unwind(AssertUnwindSafe(|| q.truncate(1))).ok(); - - assert_eq!(unsafe { DROPS }, 7); -} - -#[test] -fn test_drain_leak() { - static mut DROPS: i32 = 0; - - #[derive(Debug, PartialEq)] - struct D(u32, bool); - - impl Drop for D { - fn drop(&mut self) { - unsafe { - DROPS += 1; - } - - if self.1 { - panic!("panic in `drop`"); - } - } - } - - let mut v = VecDeque::new(); - v.push_back(D(4, false)); - v.push_back(D(5, false)); - v.push_back(D(6, false)); - v.push_front(D(3, false)); - v.push_front(D(2, true)); - v.push_front(D(1, false)); - v.push_front(D(0, false)); - - catch_unwind(AssertUnwindSafe(|| { - v.drain(1..=4); - })) - .ok(); - - assert_eq!(unsafe { DROPS }, 4); - assert_eq!(v.len(), 3); - drop(v); - assert_eq!(unsafe { DROPS }, 7); -} |
