diff options
Diffstat (limited to 'library/alloc')
72 files changed, 142 insertions, 19921 deletions
diff --git a/library/alloc/Cargo.toml b/library/alloc/Cargo.toml index 4cb83501256..dbdf292433b 100644 --- a/library/alloc/Cargo.toml +++ b/library/alloc/Cargo.toml @@ -10,32 +10,14 @@ autotests = false autobenches = false edition = "2021" +[lib] +test = false +bench = false + [dependencies] core = { path = "../core", public = true } compiler_builtins = { version = "=0.1.151", features = ['rustc-dep-of-std'] } -[dev-dependencies] -rand = { version = "0.9.0", default-features = false, features = ["alloc"] } -rand_xorshift = "0.4.0" - -[[test]] -name = "alloctests" -path = "tests/lib.rs" - -[[test]] -name = "vec_deque_alloc_error" -path = "tests/vec_deque_alloc_error.rs" - -[[bench]] -name = "allocbenches" -path = "benches/lib.rs" -test = true - -[[bench]] -name = "vec_deque_append_bench" -path = "benches/vec_deque_append.rs" -harness = false - [features] compiler-builtins-mem = ['compiler_builtins/mem'] compiler-builtins-c = ["compiler_builtins/c"] diff --git a/library/alloc/benches/binary_heap.rs b/library/alloc/benches/binary_heap.rs deleted file mode 100644 index 1b8f7f1c242..00000000000 --- a/library/alloc/benches/binary_heap.rs +++ /dev/null @@ -1,91 +0,0 @@ -use std::collections::BinaryHeap; - -use rand::seq::SliceRandom; -use test::{Bencher, black_box}; - -#[bench] -fn bench_find_smallest_1000(b: &mut Bencher) { - let mut rng = crate::bench_rng(); - let mut vec: Vec<u32> = (0..100_000).collect(); - vec.shuffle(&mut rng); - - b.iter(|| { - let mut iter = vec.iter().copied(); - let mut heap: BinaryHeap<_> = iter.by_ref().take(1000).collect(); - - for x in iter { - let mut max = heap.peek_mut().unwrap(); - // This comparison should be true only 1% of the time. - // Unnecessary `sift_down`s will degrade performance - if x < *max { - *max = x; - } - } - - heap - }) -} - -#[bench] -fn bench_peek_mut_deref_mut(b: &mut Bencher) { - let mut bheap = BinaryHeap::from(vec![42]); - let vec: Vec<u32> = (0..1_000_000).collect(); - - b.iter(|| { - let vec = black_box(&vec); - let mut peek_mut = bheap.peek_mut().unwrap(); - // The compiler shouldn't be able to optimize away the `sift_down` - // assignment in `PeekMut`'s `DerefMut` implementation since - // the loop might not run. - for &i in vec.iter() { - *peek_mut = i; - } - // Remove the already minimal overhead of the sift_down - std::mem::forget(peek_mut); - }) -} - -#[bench] -fn bench_from_vec(b: &mut Bencher) { - let mut rng = crate::bench_rng(); - let mut vec: Vec<u32> = (0..100_000).collect(); - vec.shuffle(&mut rng); - - b.iter(|| BinaryHeap::from(vec.clone())) -} - -#[bench] -fn bench_into_sorted_vec(b: &mut Bencher) { - let bheap: BinaryHeap<i32> = (0..10_000).collect(); - - b.iter(|| bheap.clone().into_sorted_vec()) -} - -#[bench] -fn bench_push(b: &mut Bencher) { - let mut bheap = BinaryHeap::with_capacity(50_000); - let mut rng = crate::bench_rng(); - let mut vec: Vec<u32> = (0..50_000).collect(); - vec.shuffle(&mut rng); - - b.iter(|| { - for &i in vec.iter() { - bheap.push(i); - } - black_box(&mut bheap); - bheap.clear(); - }) -} - -#[bench] -fn bench_pop(b: &mut Bencher) { - let mut bheap = BinaryHeap::with_capacity(10_000); - - b.iter(|| { - bheap.extend((0..10_000).rev()); - black_box(&mut bheap); - while let Some(elem) = bheap.pop() { - black_box(elem); - } - }) -} diff --git a/library/alloc/benches/btree/map.rs b/library/alloc/benches/btree/map.rs deleted file mode 100644 index 20f02dc3a96..00000000000 --- a/library/alloc/benches/btree/map.rs +++ /dev/null @@ -1,585 +0,0 @@ -use std::collections::BTreeMap; -use std::ops::RangeBounds; - -use rand::Rng; -use rand::seq::SliceRandom; -use test::{Bencher, black_box}; - -macro_rules! map_insert_rand_bench { - ($name: ident, $n: expr, $map: ident) => { - #[bench] - pub fn $name(b: &mut Bencher) { - let n: u32 = $n; - let mut map = $map::new(); - // setup - let mut rng = crate::bench_rng(); - - for _ in 0..n { - let i = rng.random::<u32>() % n; - map.insert(i, i); - } - - // measure - b.iter(|| { - let k = rng.random::<u32>() % n; - map.insert(k, k); - map.remove(&k); - }); - black_box(map); - } - }; -} - -macro_rules! map_insert_seq_bench { - ($name: ident, $n: expr, $map: ident) => { - #[bench] - pub fn $name(b: &mut Bencher) { - let mut map = $map::new(); - let n: usize = $n; - // setup - for i in 0..n { - map.insert(i * 2, i * 2); - } - - // measure - let mut i = 1; - b.iter(|| { - map.insert(i, i); - map.remove(&i); - i = (i + 2) % n; - }); - black_box(map); - } - }; -} - -macro_rules! map_from_iter_rand_bench { - ($name: ident, $n: expr, $map: ident) => { - #[bench] - pub fn $name(b: &mut Bencher) { - let n: u32 = $n; - // setup - let mut rng = crate::bench_rng(); - let mut vec = Vec::with_capacity(n as usize); - - for _ in 0..n { - let i = rng.random::<u32>() % n; - vec.push((i, i)); - } - - // measure - b.iter(|| { - let map: $map<_, _> = vec.iter().copied().collect(); - black_box(map); - }); - } - }; -} - -macro_rules! map_from_iter_seq_bench { - ($name: ident, $n: expr, $map: ident) => { - #[bench] - pub fn $name(b: &mut Bencher) { - let n: usize = $n; - // setup - let mut vec = Vec::with_capacity(n); - - for i in 0..n { - vec.push((i, i)); - } - - // measure - b.iter(|| { - let map: $map<_, _> = vec.iter().copied().collect(); - black_box(map); - }); - } - }; -} - -macro_rules! map_find_rand_bench { - ($name: ident, $n: expr, $map: ident) => { - #[bench] - pub fn $name(b: &mut Bencher) { - let mut map = $map::new(); - let n: u32 = $n; - - // setup - let mut rng = crate::bench_rng(); - let mut keys: Vec<_> = (0..n).map(|_| rng.random::<u32>() % n).collect(); - - for &k in &keys { - map.insert(k, k); - } - - keys.shuffle(&mut rng); - - // measure - let mut i = 0u32; - b.iter(|| { - let t = map.get(&keys[i as usize]); - i = (i + 1) % n; - black_box(t); - }) - } - }; -} - -macro_rules! map_find_seq_bench { - ($name: ident, $n: expr, $map: ident) => { - #[bench] - pub fn $name(b: &mut Bencher) { - let mut map = $map::new(); - let n: usize = $n; - - // setup - for i in 0..n { - map.insert(i, i); - } - - // measure - let mut i = 0; - b.iter(|| { - let x = map.get(&i); - i = (i + 1) % n; - black_box(x); - }) - } - }; -} - -map_insert_rand_bench! {insert_rand_100, 100, BTreeMap} -map_insert_rand_bench! {insert_rand_10_000, 10_000, BTreeMap} - -map_insert_seq_bench! {insert_seq_100, 100, BTreeMap} -map_insert_seq_bench! {insert_seq_10_000, 10_000, BTreeMap} - -map_from_iter_rand_bench! {from_iter_rand_100, 100, BTreeMap} -map_from_iter_rand_bench! {from_iter_rand_10_000, 10_000, BTreeMap} - -map_from_iter_seq_bench! {from_iter_seq_100, 100, BTreeMap} -map_from_iter_seq_bench! {from_iter_seq_10_000, 10_000, BTreeMap} - -map_find_rand_bench! {find_rand_100, 100, BTreeMap} -map_find_rand_bench! {find_rand_10_000, 10_000, BTreeMap} - -map_find_seq_bench! {find_seq_100, 100, BTreeMap} -map_find_seq_bench! {find_seq_10_000, 10_000, BTreeMap} - -fn bench_iteration(b: &mut Bencher, size: i32) { - let mut map = BTreeMap::<i32, i32>::new(); - let mut rng = crate::bench_rng(); - - for _ in 0..size { - map.insert(rng.random(), rng.random()); - } - - b.iter(|| { - for entry in &map { - black_box(entry); - } - }); -} - -#[bench] -pub fn iteration_20(b: &mut Bencher) { - bench_iteration(b, 20); -} - -#[bench] -pub fn iteration_1000(b: &mut Bencher) { - bench_iteration(b, 1000); -} - -#[bench] -pub fn iteration_100000(b: &mut Bencher) { - bench_iteration(b, 100000); -} - -fn bench_iteration_mut(b: &mut Bencher, size: i32) { - let mut map = BTreeMap::<i32, i32>::new(); - let mut rng = crate::bench_rng(); - - for _ in 0..size { - map.insert(rng.random(), rng.random()); - } - - b.iter(|| { - for kv in map.iter_mut() { - black_box(kv); - } - }); -} - -#[bench] -pub fn iteration_mut_20(b: &mut Bencher) { - bench_iteration_mut(b, 20); -} - -#[bench] -pub fn iteration_mut_1000(b: &mut Bencher) { - bench_iteration_mut(b, 1000); -} - -#[bench] -pub fn iteration_mut_100000(b: &mut Bencher) { - bench_iteration_mut(b, 100000); -} - -fn bench_first_and_last_nightly(b: &mut Bencher, size: i32) { - let map: BTreeMap<_, _> = (0..size).map(|i| (i, i)).collect(); - b.iter(|| { - for _ in 0..10 { - black_box(map.first_key_value()); - black_box(map.last_key_value()); - } - }); -} - -fn bench_first_and_last_stable(b: &mut Bencher, size: i32) { - let map: BTreeMap<_, _> = (0..size).map(|i| (i, i)).collect(); - b.iter(|| { - for _ in 0..10 { - black_box(map.iter().next()); - black_box(map.iter().next_back()); - } - }); -} - -#[bench] -pub fn first_and_last_0_nightly(b: &mut Bencher) { - bench_first_and_last_nightly(b, 0); -} - -#[bench] -pub fn first_and_last_0_stable(b: &mut Bencher) { - bench_first_and_last_stable(b, 0); -} - -#[bench] -pub fn first_and_last_100_nightly(b: &mut Bencher) { - bench_first_and_last_nightly(b, 100); -} - -#[bench] -pub fn first_and_last_100_stable(b: &mut Bencher) { - bench_first_and_last_stable(b, 100); -} - -#[bench] -pub fn first_and_last_10k_nightly(b: &mut Bencher) { - bench_first_and_last_nightly(b, 10_000); -} - -#[bench] -pub fn first_and_last_10k_stable(b: &mut Bencher) { - bench_first_and_last_stable(b, 10_000); -} - -const BENCH_RANGE_SIZE: i32 = 145; -const BENCH_RANGE_COUNT: i32 = BENCH_RANGE_SIZE * (BENCH_RANGE_SIZE - 1) / 2; - -fn bench_range<F, R>(b: &mut Bencher, f: F) -where - F: Fn(i32, i32) -> R, - R: RangeBounds<i32>, -{ - let map: BTreeMap<_, _> = (0..BENCH_RANGE_SIZE).map(|i| (i, i)).collect(); - b.iter(|| { - let mut c = 0; - for i in 0..BENCH_RANGE_SIZE { - for j in i + 1..BENCH_RANGE_SIZE { - let _ = black_box(map.range(f(i, j))); - c += 1; - } - } - debug_assert_eq!(c, BENCH_RANGE_COUNT); - }); -} - -#[bench] -pub fn range_included_excluded(b: &mut Bencher) { - bench_range(b, |i, j| i..j); -} - -#[bench] -pub fn range_included_included(b: &mut Bencher) { - bench_range(b, |i, j| i..=j); -} - -#[bench] -pub fn range_included_unbounded(b: &mut Bencher) { - bench_range(b, |i, _| i..); -} - -#[bench] -pub fn range_unbounded_unbounded(b: &mut Bencher) { - bench_range(b, |_, _| ..); -} - -fn bench_iter(b: &mut Bencher, repeats: i32, size: i32) { - let map: BTreeMap<_, _> = (0..size).map(|i| (i, i)).collect(); - b.iter(|| { - for _ in 0..repeats { - let _ = black_box(map.iter()); - } - }); -} - -/// Contrast range_unbounded_unbounded with `iter()`. -#[bench] -pub fn range_unbounded_vs_iter(b: &mut Bencher) { - bench_iter(b, BENCH_RANGE_COUNT, BENCH_RANGE_SIZE); -} - -#[bench] -pub fn iter_0(b: &mut Bencher) { - bench_iter(b, 1_000, 0); -} - -#[bench] -pub fn iter_1(b: &mut Bencher) { - bench_iter(b, 1_000, 1); -} - -#[bench] -pub fn iter_100(b: &mut Bencher) { - bench_iter(b, 1_000, 100); -} - -#[bench] -pub fn iter_10k(b: &mut Bencher) { - bench_iter(b, 1_000, 10_000); -} - -#[bench] -#[cfg_attr(target_os = "emscripten", ignore)] // hits an OOM -pub fn iter_1m(b: &mut Bencher) { - bench_iter(b, 1_000, 1_000_000); -} - -const FAT: usize = 256; - -// The returned map has small keys and values. -// Benchmarks on it have a counterpart in set.rs with the same keys and no values at all. -fn slim_map(n: usize) -> BTreeMap<usize, usize> { - (0..n).map(|i| (i, i)).collect::<BTreeMap<_, _>>() -} - -// The returned map has small keys and large values. -fn fat_val_map(n: usize) -> BTreeMap<usize, [usize; FAT]> { - (0..n).map(|i| (i, [i; FAT])).collect::<BTreeMap<_, _>>() -} - -#[bench] -pub fn clone_slim_100(b: &mut Bencher) { - let src = slim_map(100); - b.iter(|| src.clone()) -} - -#[bench] -pub fn clone_slim_100_and_clear(b: &mut Bencher) { - let src = slim_map(100); - b.iter(|| src.clone().clear()) -} - -#[bench] -pub fn clone_slim_100_and_drain_all(b: &mut Bencher) { - let src = slim_map(100); - b.iter(|| src.clone().extract_if(|_, _| true).count()) -} - -#[bench] -pub fn clone_slim_100_and_drain_half(b: &mut Bencher) { - let src = slim_map(100); - b.iter(|| { - let mut map = src.clone(); - assert_eq!(map.extract_if(|i, _| i % 2 == 0).count(), 100 / 2); - assert_eq!(map.len(), 100 / 2); - }) -} - -#[bench] -pub fn clone_slim_100_and_into_iter(b: &mut Bencher) { - let src = slim_map(100); - b.iter(|| src.clone().into_iter().count()) -} - -#[bench] -pub fn clone_slim_100_and_pop_all(b: &mut Bencher) { - let src = slim_map(100); - b.iter(|| { - let mut map = src.clone(); - while map.pop_first().is_some() {} - map - }); -} - -#[bench] -pub fn clone_slim_100_and_remove_all(b: &mut Bencher) { - let src = slim_map(100); - b.iter(|| { - let mut map = src.clone(); - while let Some(elt) = map.iter().map(|(&i, _)| i).next() { - let v = map.remove(&elt); - debug_assert!(v.is_some()); - } - map - }); -} - -#[bench] -pub fn clone_slim_100_and_remove_half(b: &mut Bencher) { - let src = slim_map(100); - b.iter(|| { - let mut map = src.clone(); - for i in (0..100).step_by(2) { - let v = map.remove(&i); - debug_assert!(v.is_some()); - } - assert_eq!(map.len(), 100 / 2); - map - }) -} - -#[bench] -pub fn clone_slim_10k(b: &mut Bencher) { - let src = slim_map(10_000); - b.iter(|| src.clone()) -} - -#[bench] -pub fn clone_slim_10k_and_clear(b: &mut Bencher) { - let src = slim_map(10_000); - b.iter(|| src.clone().clear()) -} - -#[bench] -pub fn clone_slim_10k_and_drain_all(b: &mut Bencher) { - let src = slim_map(10_000); - b.iter(|| src.clone().extract_if(|_, _| true).count()) -} - -#[bench] -pub fn clone_slim_10k_and_drain_half(b: &mut Bencher) { - let src = slim_map(10_000); - b.iter(|| { - let mut map = src.clone(); - assert_eq!(map.extract_if(|i, _| i % 2 == 0).count(), 10_000 / 2); - assert_eq!(map.len(), 10_000 / 2); - }) -} - -#[bench] -pub fn clone_slim_10k_and_into_iter(b: &mut Bencher) { - let src = slim_map(10_000); - b.iter(|| src.clone().into_iter().count()) -} - -#[bench] -pub fn clone_slim_10k_and_pop_all(b: &mut Bencher) { - let src = slim_map(10_000); - b.iter(|| { - let mut map = src.clone(); - while map.pop_first().is_some() {} - map - }); -} - -#[bench] -pub fn clone_slim_10k_and_remove_all(b: &mut Bencher) { - let src = slim_map(10_000); - b.iter(|| { - let mut map = src.clone(); - while let Some(elt) = map.iter().map(|(&i, _)| i).next() { - let v = map.remove(&elt); - debug_assert!(v.is_some()); - } - map - }); -} - -#[bench] -pub fn clone_slim_10k_and_remove_half(b: &mut Bencher) { - let src = slim_map(10_000); - b.iter(|| { - let mut map = src.clone(); - for i in (0..10_000).step_by(2) { - let v = map.remove(&i); - debug_assert!(v.is_some()); - } - assert_eq!(map.len(), 10_000 / 2); - map - }) -} - -#[bench] -pub fn clone_fat_val_100(b: &mut Bencher) { - let src = fat_val_map(100); - b.iter(|| src.clone()) -} - -#[bench] -pub fn clone_fat_val_100_and_clear(b: &mut Bencher) { - let src = fat_val_map(100); - b.iter(|| src.clone().clear()) -} - -#[bench] -pub fn clone_fat_val_100_and_drain_all(b: &mut Bencher) { - let src = fat_val_map(100); - b.iter(|| src.clone().extract_if(|_, _| true).count()) -} - -#[bench] -pub fn clone_fat_val_100_and_drain_half(b: &mut Bencher) { - let src = fat_val_map(100); - b.iter(|| { - let mut map = src.clone(); - assert_eq!(map.extract_if(|i, _| i % 2 == 0).count(), 100 / 2); - assert_eq!(map.len(), 100 / 2); - }) -} - -#[bench] -pub fn clone_fat_val_100_and_into_iter(b: &mut Bencher) { - let src = fat_val_map(100); - b.iter(|| src.clone().into_iter().count()) -} - -#[bench] -pub fn clone_fat_val_100_and_pop_all(b: &mut Bencher) { - let src = fat_val_map(100); - b.iter(|| { - let mut map = src.clone(); - while map.pop_first().is_some() {} - map - }); -} - -#[bench] -pub fn clone_fat_val_100_and_remove_all(b: &mut Bencher) { - let src = fat_val_map(100); - b.iter(|| { - let mut map = src.clone(); - while let Some(elt) = map.iter().map(|(&i, _)| i).next() { - let v = map.remove(&elt); - debug_assert!(v.is_some()); - } - map - }); -} - -#[bench] -pub fn clone_fat_val_100_and_remove_half(b: &mut Bencher) { - let src = fat_val_map(100); - b.iter(|| { - let mut map = src.clone(); - for i in (0..100).step_by(2) { - let v = map.remove(&i); - debug_assert!(v.is_some()); - } - assert_eq!(map.len(), 100 / 2); - map - }) -} diff --git a/library/alloc/benches/btree/mod.rs b/library/alloc/benches/btree/mod.rs deleted file mode 100644 index 095ca5dd2e2..00000000000 --- a/library/alloc/benches/btree/mod.rs +++ /dev/null @@ -1,2 +0,0 @@ -mod map; -mod set; diff --git a/library/alloc/benches/btree/set.rs b/library/alloc/benches/btree/set.rs deleted file mode 100644 index 5aa395b4d52..00000000000 --- a/library/alloc/benches/btree/set.rs +++ /dev/null @@ -1,224 +0,0 @@ -use std::collections::BTreeSet; - -use rand::Rng; -use test::Bencher; - -fn random(n: u32) -> BTreeSet<u32> { - let mut rng = crate::bench_rng(); - let mut set = BTreeSet::new(); - while set.len() < n as usize { - set.insert(rng.random()); - } - assert_eq!(set.len(), n as usize); - set -} - -fn neg(n: usize) -> BTreeSet<i32> { - let set: BTreeSet<i32> = (-(n as i32)..=-1).collect(); - assert_eq!(set.len(), n); - set -} - -fn pos(n: usize) -> BTreeSet<i32> { - let set: BTreeSet<i32> = (1..=(n as i32)).collect(); - assert_eq!(set.len(), n); - set -} - -fn stagger(n1: usize, factor: usize) -> [BTreeSet<u32>; 2] { - let n2 = n1 * factor; - let mut sets = [BTreeSet::new(), BTreeSet::new()]; - for i in 0..(n1 + n2) { - let b = i % (factor + 1) != 0; - sets[b as usize].insert(i as u32); - } - assert_eq!(sets[0].len(), n1); - assert_eq!(sets[1].len(), n2); - sets -} - -macro_rules! set_bench { - ($name: ident, $set_func: ident, $result_func: ident, $sets: expr) => { - #[bench] - pub fn $name(b: &mut Bencher) { - // setup - let sets = $sets; - - // measure - b.iter(|| sets[0].$set_func(&sets[1]).$result_func()) - } - }; -} - -fn slim_set(n: usize) -> BTreeSet<usize> { - (0..n).collect::<BTreeSet<_>>() -} - -#[bench] -pub fn clone_100(b: &mut Bencher) { - let src = slim_set(100); - b.iter(|| src.clone()) -} - -#[bench] -pub fn clone_100_and_clear(b: &mut Bencher) { - let src = slim_set(100); - b.iter(|| src.clone().clear()) -} - -#[bench] -pub fn clone_100_and_drain_all(b: &mut Bencher) { - let src = slim_set(100); - b.iter(|| src.clone().extract_if(|_| true).count()) -} - -#[bench] -pub fn clone_100_and_drain_half(b: &mut Bencher) { - let src = slim_set(100); - b.iter(|| { - let mut set = src.clone(); - assert_eq!(set.extract_if(|i| i % 2 == 0).count(), 100 / 2); - assert_eq!(set.len(), 100 / 2); - }) -} - -#[bench] -pub fn clone_100_and_into_iter(b: &mut Bencher) { - let src = slim_set(100); - b.iter(|| src.clone().into_iter().count()) -} - -#[bench] -pub fn clone_100_and_pop_all(b: &mut Bencher) { - let src = slim_set(100); - b.iter(|| { - let mut set = src.clone(); - while set.pop_first().is_some() {} - set - }); -} - -#[bench] -pub fn clone_100_and_remove_all(b: &mut Bencher) { - let src = slim_set(100); - b.iter(|| { - let mut set = src.clone(); - while let Some(elt) = set.iter().copied().next() { - let ok = set.remove(&elt); - debug_assert!(ok); - } - set - }); -} - -#[bench] -pub fn clone_100_and_remove_half(b: &mut Bencher) { - let src = slim_set(100); - b.iter(|| { - let mut set = src.clone(); - for i in (0..100).step_by(2) { - let ok = set.remove(&i); - debug_assert!(ok); - } - assert_eq!(set.len(), 100 / 2); - set - }) -} - -#[bench] -pub fn clone_10k(b: &mut Bencher) { - let src = slim_set(10_000); - b.iter(|| src.clone()) -} - -#[bench] -pub fn clone_10k_and_clear(b: &mut Bencher) { - let src = slim_set(10_000); - b.iter(|| src.clone().clear()) -} - -#[bench] -pub fn clone_10k_and_drain_all(b: &mut Bencher) { - let src = slim_set(10_000); - b.iter(|| src.clone().extract_if(|_| true).count()) -} - -#[bench] -pub fn clone_10k_and_drain_half(b: &mut Bencher) { - let src = slim_set(10_000); - b.iter(|| { - let mut set = src.clone(); - assert_eq!(set.extract_if(|i| i % 2 == 0).count(), 10_000 / 2); - assert_eq!(set.len(), 10_000 / 2); - }) -} - -#[bench] -pub fn clone_10k_and_into_iter(b: &mut Bencher) { - let src = slim_set(10_000); - b.iter(|| src.clone().into_iter().count()) -} - -#[bench] -pub fn clone_10k_and_pop_all(b: &mut Bencher) { - let src = slim_set(10_000); - b.iter(|| { - let mut set = src.clone(); - while set.pop_first().is_some() {} - set - }); -} - -#[bench] -pub fn clone_10k_and_remove_all(b: &mut Bencher) { - let src = slim_set(10_000); - b.iter(|| { - let mut set = src.clone(); - while let Some(elt) = set.iter().copied().next() { - let ok = set.remove(&elt); - debug_assert!(ok); - } - set - }); -} - -#[bench] -pub fn clone_10k_and_remove_half(b: &mut Bencher) { - let src = slim_set(10_000); - b.iter(|| { - let mut set = src.clone(); - for i in (0..10_000).step_by(2) { - let ok = set.remove(&i); - debug_assert!(ok); - } - assert_eq!(set.len(), 10_000 / 2); - set - }) -} - -set_bench! {intersection_100_neg_vs_100_pos, intersection, count, [neg(100), pos(100)]} -set_bench! {intersection_100_neg_vs_10k_pos, intersection, count, [neg(100), pos(10_000)]} -set_bench! {intersection_100_pos_vs_100_neg, intersection, count, [pos(100), neg(100)]} -set_bench! {intersection_100_pos_vs_10k_neg, intersection, count, [pos(100), neg(10_000)]} -set_bench! {intersection_10k_neg_vs_100_pos, intersection, count, [neg(10_000), pos(100)]} -set_bench! {intersection_10k_neg_vs_10k_pos, intersection, count, [neg(10_000), pos(10_000)]} -set_bench! {intersection_10k_pos_vs_100_neg, intersection, count, [pos(10_000), neg(100)]} -set_bench! {intersection_10k_pos_vs_10k_neg, intersection, count, [pos(10_000), neg(10_000)]} -set_bench! {intersection_random_100_vs_100, intersection, count, [random(100), random(100)]} -set_bench! {intersection_random_100_vs_10k, intersection, count, [random(100), random(10_000)]} -set_bench! {intersection_random_10k_vs_100, intersection, count, [random(10_000), random(100)]} -set_bench! {intersection_random_10k_vs_10k, intersection, count, [random(10_000), random(10_000)]} -set_bench! {intersection_staggered_100_vs_100, intersection, count, stagger(100, 1)} -set_bench! {intersection_staggered_10k_vs_10k, intersection, count, stagger(10_000, 1)} -set_bench! {intersection_staggered_100_vs_10k, intersection, count, stagger(100, 100)} -set_bench! {difference_random_100_vs_100, difference, count, [random(100), random(100)]} -set_bench! {difference_random_100_vs_10k, difference, count, [random(100), random(10_000)]} -set_bench! {difference_random_10k_vs_100, difference, count, [random(10_000), random(100)]} -set_bench! {difference_random_10k_vs_10k, difference, count, [random(10_000), random(10_000)]} -set_bench! {difference_staggered_100_vs_100, difference, count, stagger(100, 1)} -set_bench! {difference_staggered_10k_vs_10k, difference, count, stagger(10_000, 1)} -set_bench! {difference_staggered_100_vs_10k, difference, count, stagger(100, 100)} -set_bench! {is_subset_100_vs_100, is_subset, clone, [pos(100), pos(100)]} -set_bench! {is_subset_100_vs_10k, is_subset, clone, [pos(100), pos(10_000)]} -set_bench! {is_subset_10k_vs_100, is_subset, clone, [pos(10_000), pos(100)]} -set_bench! {is_subset_10k_vs_10k, is_subset, clone, [pos(10_000), pos(10_000)]} diff --git a/library/alloc/benches/lib.rs b/library/alloc/benches/lib.rs deleted file mode 100644 index 2633154318c..00000000000 --- a/library/alloc/benches/lib.rs +++ /dev/null @@ -1,28 +0,0 @@ -// Disabling in Miri as these would take too long. -#![cfg(not(miri))] -#![feature(btree_extract_if)] -#![feature(iter_next_chunk)] -#![feature(repr_simd)] -#![feature(slice_partition_dedup)] -#![feature(strict_provenance_lints)] -#![feature(test)] -#![deny(fuzzy_provenance_casts)] - -extern crate test; - -mod binary_heap; -mod btree; -mod linked_list; -mod slice; -mod str; -mod string; -mod vec; -mod vec_deque; - -/// Returns a `rand::Rng` seeded with a consistent seed. -/// -/// This is done to avoid introducing nondeterminism in benchmark results. -fn bench_rng() -> rand_xorshift::XorShiftRng { - const SEED: [u8; 16] = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15]; - rand::SeedableRng::from_seed(SEED) -} diff --git a/library/alloc/benches/linked_list.rs b/library/alloc/benches/linked_list.rs deleted file mode 100644 index b9322b6d4c3..00000000000 --- a/library/alloc/benches/linked_list.rs +++ /dev/null @@ -1,78 +0,0 @@ -use std::collections::LinkedList; - -use test::Bencher; - -#[bench] -fn bench_collect_into(b: &mut Bencher) { - let v = &[0; 64]; - b.iter(|| { - let _: LinkedList<_> = v.iter().cloned().collect(); - }) -} - -#[bench] -fn bench_push_front(b: &mut Bencher) { - let mut m: LinkedList<_> = LinkedList::new(); - b.iter(|| { - m.push_front(0); - }) -} - -#[bench] -fn bench_push_back(b: &mut Bencher) { - let mut m: LinkedList<_> = LinkedList::new(); - b.iter(|| { - m.push_back(0); - }) -} - -#[bench] -fn bench_push_back_pop_back(b: &mut Bencher) { - let mut m: LinkedList<_> = LinkedList::new(); - b.iter(|| { - m.push_back(0); - m.pop_back(); - }) -} - -#[bench] -fn bench_push_front_pop_front(b: &mut Bencher) { - let mut m: LinkedList<_> = LinkedList::new(); - b.iter(|| { - m.push_front(0); - m.pop_front(); - }) -} - -#[bench] -fn bench_iter(b: &mut Bencher) { - let v = &[0; 128]; - let m: LinkedList<_> = v.iter().cloned().collect(); - b.iter(|| { - assert!(m.iter().count() == 128); - }) -} -#[bench] -fn bench_iter_mut(b: &mut Bencher) { - let v = &[0; 128]; - let mut m: LinkedList<_> = v.iter().cloned().collect(); - b.iter(|| { - assert!(m.iter_mut().count() == 128); - }) -} -#[bench] -fn bench_iter_rev(b: &mut Bencher) { - let v = &[0; 128]; - let m: LinkedList<_> = v.iter().cloned().collect(); - b.iter(|| { - assert!(m.iter().rev().count() == 128); - }) -} -#[bench] -fn bench_iter_mut_rev(b: &mut Bencher) { - let v = &[0; 128]; - let mut m: LinkedList<_> = v.iter().cloned().collect(); - b.iter(|| { - assert!(m.iter_mut().rev().count() == 128); - }) -} diff --git a/library/alloc/benches/slice.rs b/library/alloc/benches/slice.rs deleted file mode 100644 index 27b0e6fac0a..00000000000 --- a/library/alloc/benches/slice.rs +++ /dev/null @@ -1,390 +0,0 @@ -use std::ptr; - -use rand::Rng; -use rand::distr::{Alphanumeric, SampleString, StandardUniform}; -use test::{Bencher, black_box}; - -#[bench] -fn iterator(b: &mut Bencher) { - // peculiar numbers to stop LLVM from optimising the summation - // out. - let v: Vec<_> = (0..100).map(|i| i ^ (i << 1) ^ (i >> 1)).collect(); - - b.iter(|| { - let mut sum = 0; - for x in &v { - sum += *x; - } - // sum == 11806, to stop dead code elimination. - if sum == 0 { - panic!() - } - }) -} - -#[bench] -fn mut_iterator(b: &mut Bencher) { - let mut v = vec![0; 100]; - - b.iter(|| { - let mut i = 0; - for x in &mut v { - *x = i; - i += 1; - } - }) -} - -#[bench] -fn concat(b: &mut Bencher) { - let xss: Vec<Vec<i32>> = (0..100).map(|i| (0..i).collect()).collect(); - b.iter(|| { - xss.concat(); - }); -} - -#[bench] -fn join(b: &mut Bencher) { - let xss: Vec<Vec<i32>> = (0..100).map(|i| (0..i).collect()).collect(); - b.iter(|| xss.join(&0)); -} - -#[bench] -fn push(b: &mut Bencher) { - let mut vec = Vec::<i32>::new(); - b.iter(|| { - vec.push(0); - black_box(&vec); - }); -} - -#[bench] -fn starts_with_same_vector(b: &mut Bencher) { - let vec: Vec<_> = (0..100).collect(); - b.iter(|| vec.starts_with(&vec)) -} - -#[bench] -fn starts_with_single_element(b: &mut Bencher) { - let vec: Vec<_> = vec![0]; - b.iter(|| vec.starts_with(&vec)) -} - -#[bench] -fn starts_with_diff_one_element_at_end(b: &mut Bencher) { - let vec: Vec<_> = (0..100).collect(); - let mut match_vec: Vec<_> = (0..99).collect(); - match_vec.push(0); - b.iter(|| vec.starts_with(&match_vec)) -} - -#[bench] -fn ends_with_same_vector(b: &mut Bencher) { - let vec: Vec<_> = (0..100).collect(); - b.iter(|| vec.ends_with(&vec)) -} - -#[bench] -fn ends_with_single_element(b: &mut Bencher) { - let vec: Vec<_> = vec![0]; - b.iter(|| vec.ends_with(&vec)) -} - -#[bench] -fn ends_with_diff_one_element_at_beginning(b: &mut Bencher) { - let vec: Vec<_> = (0..100).collect(); - let mut match_vec: Vec<_> = (0..100).collect(); - match_vec[0] = 200; - b.iter(|| vec.starts_with(&match_vec)) -} - -#[bench] -fn contains_last_element(b: &mut Bencher) { - let vec: Vec<_> = (0..100).collect(); - b.iter(|| vec.contains(&99)) -} - -#[bench] -fn zero_1kb_from_elem(b: &mut Bencher) { - b.iter(|| vec![0u8; 1024]); -} - -#[bench] -fn zero_1kb_set_memory(b: &mut Bencher) { - b.iter(|| { - let mut v = Vec::<u8>::with_capacity(1024); - unsafe { - let vp = v.as_mut_ptr(); - ptr::write_bytes(vp, 0, 1024); - v.set_len(1024); - } - v - }); -} - -#[bench] -fn zero_1kb_loop_set(b: &mut Bencher) { - b.iter(|| { - let mut v = Vec::<u8>::with_capacity(1024); - unsafe { - v.set_len(1024); - } - for i in 0..1024 { - v[i] = 0; - } - }); -} - -#[bench] -fn zero_1kb_mut_iter(b: &mut Bencher) { - b.iter(|| { - let mut v = Vec::<u8>::with_capacity(1024); - unsafe { - v.set_len(1024); - } - for x in &mut v { - *x = 0; - } - v - }); -} - -#[bench] -fn random_inserts(b: &mut Bencher) { - let mut rng = crate::bench_rng(); - b.iter(|| { - let mut v = vec![(0, 0); 30]; - for _ in 0..100 { - let l = v.len(); - v.insert(rng.random::<u32>() as usize % (l + 1), (1, 1)); - } - }) -} - -#[bench] -fn random_removes(b: &mut Bencher) { - let mut rng = crate::bench_rng(); - b.iter(|| { - let mut v = vec![(0, 0); 130]; - for _ in 0..100 { - let l = v.len(); - v.remove(rng.random::<u32>() as usize % l); - } - }) -} - -fn gen_ascending(len: usize) -> Vec<u64> { - (0..len as u64).collect() -} - -fn gen_descending(len: usize) -> Vec<u64> { - (0..len as u64).rev().collect() -} - -fn gen_random(len: usize) -> Vec<u64> { - let mut rng = crate::bench_rng(); - (&mut rng).sample_iter(&StandardUniform).take(len).collect() -} - -fn gen_random_bytes(len: usize) -> Vec<u8> { - let mut rng = crate::bench_rng(); - (&mut rng).sample_iter(&StandardUniform).take(len).collect() -} - -fn gen_mostly_ascending(len: usize) -> Vec<u64> { - let mut rng = crate::bench_rng(); - let mut v = gen_ascending(len); - for _ in (0usize..).take_while(|x| x * x <= len) { - let x = rng.random::<u32>() as usize % len; - let y = rng.random::<u32>() as usize % len; - v.swap(x, y); - } - v -} - -fn gen_mostly_descending(len: usize) -> Vec<u64> { - let mut rng = crate::bench_rng(); - let mut v = gen_descending(len); - for _ in (0usize..).take_while(|x| x * x <= len) { - let x = rng.random::<u32>() as usize % len; - let y = rng.random::<u32>() as usize % len; - v.swap(x, y); - } - v -} - -fn gen_strings(len: usize) -> Vec<String> { - let mut rng = crate::bench_rng(); - let mut v = vec![]; - for _ in 0..len { - let n = rng.random::<u32>() % 20 + 1; - v.push(Alphanumeric.sample_string(&mut rng, n as usize)); - } - v -} - -fn gen_big_random(len: usize) -> Vec<[u64; 16]> { - let mut rng = crate::bench_rng(); - (&mut rng).sample_iter(&StandardUniform).map(|x| [x; 16]).take(len).collect() -} - -macro_rules! sort { - ($f:ident, $name:ident, $gen:expr, $len:expr) => { - #[bench] - fn $name(b: &mut Bencher) { - let v = $gen($len); - b.iter(|| v.clone().$f()); - b.bytes = $len * size_of_val(&$gen(1)[0]) as u64; - } - }; -} - -macro_rules! sort_strings { - ($f:ident, $name:ident, $gen:expr, $len:expr) => { - #[bench] - fn $name(b: &mut Bencher) { - let v = $gen($len); - let v = v.iter().map(|s| &**s).collect::<Vec<&str>>(); - b.iter(|| v.clone().$f()); - b.bytes = $len * size_of::<&str>() as u64; - } - }; -} - -macro_rules! sort_expensive { - ($f:ident, $name:ident, $gen:expr, $len:expr) => { - #[bench] - fn $name(b: &mut Bencher) { - let v = $gen($len); - b.iter(|| { - let mut v = v.clone(); - let mut count = 0; - v.$f(|a: &u64, b: &u64| { - count += 1; - if count % 1_000_000_000 == 0 { - panic!("should not happen"); - } - (*a as f64).cos().partial_cmp(&(*b as f64).cos()).unwrap() - }); - black_box(count); - }); - b.bytes = $len * size_of_val(&$gen(1)[0]) as u64; - } - }; -} - -macro_rules! sort_lexicographic { - ($f:ident, $name:ident, $gen:expr, $len:expr) => { - #[bench] - fn $name(b: &mut Bencher) { - let v = $gen($len); - b.iter(|| v.clone().$f(|x| x.to_string())); - b.bytes = $len * size_of_val(&$gen(1)[0]) as u64; - } - }; -} - -sort!(sort, sort_small_ascending, gen_ascending, 10); -sort!(sort, sort_small_descending, gen_descending, 10); -sort!(sort, sort_small_random, gen_random, 10); -sort!(sort, sort_small_big, gen_big_random, 10); -sort!(sort, sort_medium_random, gen_random, 100); -sort!(sort, sort_large_ascending, gen_ascending, 10000); -sort!(sort, sort_large_descending, gen_descending, 10000); -sort!(sort, sort_large_mostly_ascending, gen_mostly_ascending, 10000); -sort!(sort, sort_large_mostly_descending, gen_mostly_descending, 10000); -sort!(sort, sort_large_random, gen_random, 10000); -sort!(sort, sort_large_big, gen_big_random, 10000); -sort_strings!(sort, sort_large_strings, gen_strings, 10000); -sort_expensive!(sort_by, sort_large_expensive, gen_random, 10000); - -sort!(sort_unstable, sort_unstable_small_ascending, gen_ascending, 10); -sort!(sort_unstable, sort_unstable_small_descending, gen_descending, 10); -sort!(sort_unstable, sort_unstable_small_random, gen_random, 10); -sort!(sort_unstable, sort_unstable_small_big, gen_big_random, 10); -sort!(sort_unstable, sort_unstable_medium_random, gen_random, 100); -sort!(sort_unstable, sort_unstable_large_ascending, gen_ascending, 10000); -sort!(sort_unstable, sort_unstable_large_descending, gen_descending, 10000); -sort!(sort_unstable, sort_unstable_large_mostly_ascending, gen_mostly_ascending, 10000); -sort!(sort_unstable, sort_unstable_large_mostly_descending, gen_mostly_descending, 10000); -sort!(sort_unstable, sort_unstable_large_random, gen_random, 10000); -sort!(sort_unstable, sort_unstable_large_big, gen_big_random, 10000); -sort_strings!(sort_unstable, sort_unstable_large_strings, gen_strings, 10000); -sort_expensive!(sort_unstable_by, sort_unstable_large_expensive, gen_random, 10000); - -sort_lexicographic!(sort_by_key, sort_by_key_lexicographic, gen_random, 10000); -sort_lexicographic!(sort_unstable_by_key, sort_unstable_by_key_lexicographic, gen_random, 10000); -sort_lexicographic!(sort_by_cached_key, sort_by_cached_key_lexicographic, gen_random, 10000); - -macro_rules! reverse { - ($name:ident, $ty:ty, $f:expr) => { - #[bench] - fn $name(b: &mut Bencher) { - // odd length and offset by 1 to be as unaligned as possible - let n = 0xFFFFF; - let mut v: Vec<_> = (0..1 + (n / size_of::<$ty>() as u64)).map($f).collect(); - b.iter(|| black_box(&mut v[1..]).reverse()); - b.bytes = n; - } - }; -} - -reverse!(reverse_u8, u8, |x| x as u8); -reverse!(reverse_u16, u16, |x| x as u16); -reverse!(reverse_u8x3, [u8; 3], |x| [x as u8, (x >> 8) as u8, (x >> 16) as u8]); -reverse!(reverse_u32, u32, |x| x as u32); -reverse!(reverse_u64, u64, |x| x as u64); -reverse!(reverse_u128, u128, |x| x as u128); -#[repr(simd)] -struct F64x4([f64; 4]); -reverse!(reverse_simd_f64x4, F64x4, |x| { - let x = x as f64; - F64x4([x, x, x, x]) -}); - -macro_rules! rotate { - ($name:ident, $gen:expr, $len:expr, $mid:expr) => { - #[bench] - fn $name(b: &mut Bencher) { - let size = size_of_val(&$gen(1)[0]); - let mut v = $gen($len * 8 / size); - b.iter(|| black_box(&mut v).rotate_left(($mid * 8 + size - 1) / size)); - b.bytes = (v.len() * size) as u64; - } - }; -} - -rotate!(rotate_tiny_by1, gen_random, 16, 1); -rotate!(rotate_tiny_half, gen_random, 16, 16 / 2); -rotate!(rotate_tiny_half_plus_one, gen_random, 16, 16 / 2 + 1); - -rotate!(rotate_medium_by1, gen_random, 9158, 1); -rotate!(rotate_medium_by727_u64, gen_random, 9158, 727); -rotate!(rotate_medium_by727_bytes, gen_random_bytes, 9158, 727); -rotate!(rotate_medium_by727_strings, gen_strings, 9158, 727); -rotate!(rotate_medium_half, gen_random, 9158, 9158 / 2); -rotate!(rotate_medium_half_plus_one, gen_random, 9158, 9158 / 2 + 1); - -// Intended to use more RAM than the machine has cache -#[cfg(not(target_os = "emscripten"))] // hits an OOM -rotate!(rotate_huge_by1, gen_random, 5 * 1024 * 1024, 1); -#[cfg(not(target_os = "emscripten"))] // hits an OOM -rotate!(rotate_huge_by9199_u64, gen_random, 5 * 1024 * 1024, 9199); -#[cfg(not(target_os = "emscripten"))] // hits an OOM -rotate!(rotate_huge_by9199_bytes, gen_random_bytes, 5 * 1024 * 1024, 9199); -#[cfg(not(target_os = "emscripten"))] // hits an OOM -rotate!(rotate_huge_by9199_strings, gen_strings, 5 * 1024 * 1024, 9199); -#[cfg(not(target_os = "emscripten"))] // hits an OOM -rotate!(rotate_huge_by9199_big, gen_big_random, 5 * 1024 * 1024, 9199); -#[cfg(not(target_os = "emscripten"))] // hits an OOM -rotate!(rotate_huge_by1234577_u64, gen_random, 5 * 1024 * 1024, 1234577); -#[cfg(not(target_os = "emscripten"))] // hits an OOM -rotate!(rotate_huge_by1234577_bytes, gen_random_bytes, 5 * 1024 * 1024, 1234577); -#[cfg(not(target_os = "emscripten"))] // hits an OOM -rotate!(rotate_huge_by1234577_strings, gen_strings, 5 * 1024 * 1024, 1234577); -#[cfg(not(target_os = "emscripten"))] // hits an OOM -rotate!(rotate_huge_by1234577_big, gen_big_random, 5 * 1024 * 1024, 1234577); -#[cfg(not(target_os = "emscripten"))] // hits an OOM -rotate!(rotate_huge_half, gen_random, 5 * 1024 * 1024, 5 * 1024 * 1024 / 2); -#[cfg(not(target_os = "emscripten"))] // hits an OOM -rotate!(rotate_huge_half_plus_one, gen_random, 5 * 1024 * 1024, 5 * 1024 * 1024 / 2 + 1); diff --git a/library/alloc/benches/str.rs b/library/alloc/benches/str.rs deleted file mode 100644 index 98c7c5413ca..00000000000 --- a/library/alloc/benches/str.rs +++ /dev/null @@ -1,351 +0,0 @@ -use test::{Bencher, black_box}; - -#[bench] -fn char_iterator(b: &mut Bencher) { - let s = "ศไทย中华Việt Nam; Mary had a little lamb, Little lamb"; - - b.iter(|| s.chars().count()); -} - -#[bench] -fn char_iterator_for(b: &mut Bencher) { - let s = "ศไทย中华Việt Nam; Mary had a little lamb, Little lamb"; - - b.iter(|| { - for ch in s.chars() { - black_box(ch); - } - }); -} - -#[bench] -fn char_iterator_ascii(b: &mut Bencher) { - let s = "Mary had a little lamb, Little lamb - Mary had a little lamb, Little lamb - Mary had a little lamb, Little lamb - Mary had a little lamb, Little lamb - Mary had a little lamb, Little lamb - Mary had a little lamb, Little lamb"; - - b.iter(|| s.chars().count()); -} - -#[bench] -fn char_iterator_rev(b: &mut Bencher) { - let s = "ศไทย中华Việt Nam; Mary had a little lamb, Little lamb"; - - b.iter(|| s.chars().rev().count()); -} - -#[bench] -fn char_iterator_rev_for(b: &mut Bencher) { - let s = "ศไทย中华Việt Nam; Mary had a little lamb, Little lamb"; - - b.iter(|| { - for ch in s.chars().rev() { - black_box(ch); - } - }); -} - -#[bench] -fn char_indicesator(b: &mut Bencher) { - let s = "ศไทย中华Việt Nam; Mary had a little lamb, Little lamb"; - let len = s.chars().count(); - - b.iter(|| assert_eq!(s.char_indices().count(), len)); -} - -#[bench] -fn char_indicesator_rev(b: &mut Bencher) { - let s = "ศไทย中华Việt Nam; Mary had a little lamb, Little lamb"; - let len = s.chars().count(); - - b.iter(|| assert_eq!(s.char_indices().rev().count(), len)); -} - -#[bench] -fn split_unicode_ascii(b: &mut Bencher) { - let s = "ประเทศไทย中华Việt Namประเทศไทย中华Việt Nam"; - - b.iter(|| assert_eq!(s.split('V').count(), 3)); -} - -#[bench] -fn split_ascii(b: &mut Bencher) { - let s = "Mary had a little lamb, Little lamb, little-lamb."; - let len = s.split(' ').count(); - - b.iter(|| assert_eq!(s.split(' ').count(), len)); -} - -#[bench] -fn split_extern_fn(b: &mut Bencher) { - let s = "Mary had a little lamb, Little lamb, little-lamb."; - let len = s.split(' ').count(); - fn pred(c: char) -> bool { - c == ' ' - } - - b.iter(|| assert_eq!(s.split(pred).count(), len)); -} - -#[bench] -fn split_closure(b: &mut Bencher) { - let s = "Mary had a little lamb, Little lamb, little-lamb."; - let len = s.split(' ').count(); - - b.iter(|| assert_eq!(s.split(|c: char| c == ' ').count(), len)); -} - -#[bench] -fn split_slice(b: &mut Bencher) { - let s = "Mary had a little lamb, Little lamb, little-lamb."; - let len = s.split(' ').count(); - - let c: &[char] = &[' ']; - b.iter(|| assert_eq!(s.split(c).count(), len)); -} - -#[bench] -fn bench_join(b: &mut Bencher) { - let s = "ศไทย中华Việt Nam; Mary had a little lamb, Little lamb"; - let sep = "→"; - let v = vec![s, s, s, s, s, s, s, s, s, s]; - b.iter(|| { - assert_eq!(v.join(sep).len(), s.len() * 10 + sep.len() * 9); - }) -} - -#[bench] -fn bench_contains_short_short(b: &mut Bencher) { - let haystack = "Lorem ipsum dolor sit amet, consectetur adipiscing elit."; - let needle = "sit"; - - b.bytes = haystack.len() as u64; - b.iter(|| { - assert!(black_box(haystack).contains(black_box(needle))); - }) -} - -static LONG_HAYSTACK: &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. - -In est dui, tincidunt sed tempus interdum, adipiscing laoreet ante. Etiam tempor, tellus quis \ -sagittis interdum, nulla purus mattis sem, quis auctor erat odio ac tellus. In nec nunc sit amet \ -diam volutpat molestie at sed ipsum. Vestibulum laoreet consequat vulputate. Integer accumsan \ -lorem ac dignissim placerat. Suspendisse convallis faucibus lorem. Aliquam erat volutpat. In vel \ -eleifend felis. Sed suscipit nulla lorem, sed mollis est sollicitudin et. Nam fermentum egestas \ -interdum. Curabitur ut nisi justo. - -Sed sollicitudin ipsum tellus, ut condimentum leo eleifend nec. Cras ut velit ante. Phasellus nec \ -mollis odio. Mauris molestie erat in arcu mattis, at aliquet dolor vehicula. Quisque malesuada \ -lectus sit amet nisi pretium, a condimentum ipsum porta. Morbi at dapibus diam. Praesent egestas \ -est sed risus elementum, eu rutrum metus ultrices. Etiam fermentum consectetur magna, id rutrum \ -felis accumsan a. Aliquam ut pellentesque libero. Sed mi nulla, lobortis eu tortor id, suscipit \ -ultricies neque. Morbi iaculis sit amet risus at iaculis. Praesent eget ligula quis turpis \ -feugiat suscipit vel non arcu. Interdum et malesuada fames ac ante ipsum primis in faucibus. \ -Aliquam sit amet placerat lorem. - -Cras a lacus vel ante posuere elementum. Nunc est leo, bibendum ut facilisis vel, bibendum at \ -mauris. Nullam adipiscing diam vel odio ornare, luctus adipiscing mi luctus. Nulla facilisi. \ -Mauris adipiscing bibendum neque, quis adipiscing lectus tempus et. Sed feugiat erat et nisl \ -lobortis pharetra. Donec vitae erat enim. Nullam sit amet felis et quam lacinia tincidunt. Aliquam \ -suscipit dapibus urna. Sed volutpat urna in magna pulvinar volutpat. Phasellus nec tellus ac diam \ -cursus accumsan. - -Nam lectus enim, dapibus non nisi tempor, consectetur convallis massa. Maecenas eleifend dictum \ -feugiat. Etiam quis mauris vel risus luctus mattis a a nunc. Nullam orci quam, imperdiet id \ -vehicula in, porttitor ut nibh. Duis sagittis adipiscing nisl vitae congue. Donec mollis risus eu \ -leo suscipit, varius porttitor nulla porta. Pellentesque ut sem nec nisi euismod vehicula. Nulla \ -malesuada sollicitudin quam eu fermentum."; - -#[bench] -fn bench_contains_2b_repeated_long(b: &mut Bencher) { - let haystack = LONG_HAYSTACK; - let needle = "::"; - - b.bytes = haystack.len() as u64; - b.iter(|| { - assert!(!black_box(haystack).contains(black_box(needle))); - }) -} - -#[bench] -fn bench_contains_short_long(b: &mut Bencher) { - let haystack = LONG_HAYSTACK; - let needle = "english"; - - b.bytes = haystack.len() as u64; - b.iter(|| { - assert!(!black_box(haystack).contains(black_box(needle))); - }) -} - -#[bench] -fn bench_contains_16b_in_long(b: &mut Bencher) { - let haystack = LONG_HAYSTACK; - let needle = "english language"; - - b.bytes = haystack.len() as u64; - b.iter(|| { - assert!(!black_box(haystack).contains(black_box(needle))); - }) -} - -#[bench] -fn bench_contains_32b_in_long(b: &mut Bencher) { - let haystack = LONG_HAYSTACK; - let needle = "the english language sample text"; - - b.bytes = haystack.len() as u64; - b.iter(|| { - assert!(!black_box(haystack).contains(black_box(needle))); - }) -} - -#[bench] -fn bench_contains_bad_naive(b: &mut Bencher) { - let haystack = "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"; - let needle = "aaaaaaaab"; - - b.bytes = haystack.len() as u64; - b.iter(|| { - assert!(!black_box(haystack).contains(black_box(needle))); - }) -} - -#[bench] -fn bench_contains_bad_simd(b: &mut Bencher) { - let haystack = "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"; - let needle = "aaabaaaa"; - - b.bytes = haystack.len() as u64; - b.iter(|| { - assert!(!black_box(haystack).contains(black_box(needle))); - }) -} - -#[bench] -fn bench_contains_equal(b: &mut Bencher) { - let haystack = "Lorem ipsum dolor sit amet, consectetur adipiscing elit."; - let needle = "Lorem ipsum dolor sit amet, consectetur adipiscing elit."; - - b.bytes = haystack.len() as u64; - b.iter(|| { - assert!(black_box(haystack).contains(black_box(needle))); - }) -} - -macro_rules! make_test_inner { - ($s:ident, $code:expr, $name:ident, $str:expr, $iters:expr) => { - #[bench] - fn $name(bencher: &mut Bencher) { - let mut $s = $str; - black_box(&mut $s); - bencher.iter(|| { - for _ in 0..$iters { - black_box($code); - } - }); - } - }; -} - -macro_rules! make_test { - ($name:ident, $s:ident, $code:expr) => { - make_test!($name, $s, $code, 1); - }; - ($name:ident, $s:ident, $code:expr, $iters:expr) => { - mod $name { - use test::Bencher; - use test::black_box; - - // Short strings: 65 bytes each - make_test_inner!($s, $code, short_ascii, - "Mary had a little lamb, Little lamb Mary had a littl lamb, lamb!", $iters); - make_test_inner!($s, $code, short_mixed, - "ศไทย中华Việt Nam; Mary had a little lamb, Little lam!", $iters); - make_test_inner!($s, $code, short_pile_of_poo, - "💩💩💩💩💩💩💩💩💩💩💩💩💩💩💩💩!", $iters); - make_test_inner!($s, $code, long_lorem_ipsum,"\ -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. - -In est dui, tincidunt sed tempus interdum, adipiscing laoreet ante. Etiam tempor, tellus quis \ -sagittis interdum, nulla purus mattis sem, quis auctor erat odio ac tellus. In nec nunc sit amet \ -diam volutpat molestie at sed ipsum. Vestibulum laoreet consequat vulputate. Integer accumsan \ -lorem ac dignissim placerat. Suspendisse convallis faucibus lorem. Aliquam erat volutpat. In vel \ -eleifend felis. Sed suscipit nulla lorem, sed mollis est sollicitudin et. Nam fermentum egestas \ -interdum. Curabitur ut nisi justo. - -Sed sollicitudin ipsum tellus, ut condimentum leo eleifend nec. Cras ut velit ante. Phasellus nec \ -mollis odio. Mauris molestie erat in arcu mattis, at aliquet dolor vehicula. Quisque malesuada \ -lectus sit amet nisi pretium, a condimentum ipsum porta. Morbi at dapibus diam. Praesent egestas \ -est sed risus elementum, eu rutrum metus ultrices. Etiam fermentum consectetur magna, id rutrum \ -felis accumsan a. Aliquam ut pellentesque libero. Sed mi nulla, lobortis eu tortor id, suscipit \ -ultricies neque. Morbi iaculis sit amet risus at iaculis. Praesent eget ligula quis turpis \ -feugiat suscipit vel non arcu. Interdum et malesuada fames ac ante ipsum primis in faucibus. \ -Aliquam sit amet placerat lorem. - -Cras a lacus vel ante posuere elementum. Nunc est leo, bibendum ut facilisis vel, bibendum at \ -mauris. Nullam adipiscing diam vel odio ornare, luctus adipiscing mi luctus. Nulla facilisi. \ -Mauris adipiscing bibendum neque, quis adipiscing lectus tempus et. Sed feugiat erat et nisl \ -lobortis pharetra. Donec vitae erat enim. Nullam sit amet felis et quam lacinia tincidunt. Aliquam \ -suscipit dapibus urna. Sed volutpat urna in magna pulvinar volutpat. Phasellus nec tellus ac diam \ -cursus accumsan. - -Nam lectus enim, dapibus non nisi tempor, consectetur convallis massa. Maecenas eleifend dictum \ -feugiat. Etiam quis mauris vel risus luctus mattis a a nunc. Nullam orci quam, imperdiet id \ -vehicula in, porttitor ut nibh. Duis sagittis adipiscing nisl vitae congue. Donec mollis risus eu \ -leo suscipit, varius porttitor nulla porta. Pellentesque ut sem nec nisi euismod vehicula. Nulla \ -malesuada sollicitudin quam eu fermentum!", $iters); - } - } -} - -make_test!(chars_count, s, s.chars().count()); - -make_test!(contains_bang_str, s, s.contains("!")); -make_test!(contains_bang_char, s, s.contains('!')); - -make_test!(match_indices_a_str, s, s.match_indices("a").count()); - -make_test!(split_a_str, s, s.split("a").count()); - -make_test!(trim_ascii_char, s, { s.trim_matches(|c: char| c.is_ascii()) }); -make_test!(trim_start_ascii_char, s, { s.trim_start_matches(|c: char| c.is_ascii()) }); -make_test!(trim_end_ascii_char, s, { s.trim_end_matches(|c: char| c.is_ascii()) }); - -make_test!(find_underscore_char, s, s.find('_')); -make_test!(rfind_underscore_char, s, s.rfind('_')); -make_test!(find_underscore_str, s, s.find("_")); - -make_test!(find_zzz_char, s, s.find('\u{1F4A4}')); -make_test!(rfind_zzz_char, s, s.rfind('\u{1F4A4}')); -make_test!(find_zzz_str, s, s.find("\u{1F4A4}")); - -make_test!(starts_with_ascii_char, s, s.starts_with('/'), 1024); -make_test!(ends_with_ascii_char, s, s.ends_with('/'), 1024); -make_test!(starts_with_unichar, s, s.starts_with('\u{1F4A4}'), 1024); -make_test!(ends_with_unichar, s, s.ends_with('\u{1F4A4}'), 1024); -make_test!(starts_with_str, s, s.starts_with("💩💩💩💩💩💩💩💩💩💩💩💩💩💩💩💩"), 1024); -make_test!(ends_with_str, s, s.ends_with("💩💩💩💩💩💩💩💩💩💩💩💩💩💩💩💩"), 1024); - -make_test!(split_space_char, s, s.split(' ').count()); -make_test!(split_terminator_space_char, s, s.split_terminator(' ').count()); - -make_test!(splitn_space_char, s, s.splitn(10, ' ').count()); -make_test!(rsplitn_space_char, s, s.rsplitn(10, ' ').count()); - -make_test!(split_space_str, s, s.split(" ").count()); -make_test!(split_ad_str, s, s.split("ad").count()); - -make_test!(to_lowercase, s, s.to_lowercase()); diff --git a/library/alloc/benches/string.rs b/library/alloc/benches/string.rs deleted file mode 100644 index 3d79ab78c69..00000000000 --- a/library/alloc/benches/string.rs +++ /dev/null @@ -1,165 +0,0 @@ -use std::iter::repeat; - -use test::{Bencher, black_box}; - -#[bench] -fn bench_with_capacity(b: &mut Bencher) { - b.iter(|| String::with_capacity(100)); -} - -#[bench] -fn bench_push_str(b: &mut Bencher) { - let s = "ศไทย中华Việt Nam; Mary had a little lamb, Little lamb"; - b.iter(|| { - let mut r = String::new(); - r.push_str(s); - }); -} - -const REPETITIONS: u64 = 10_000; - -#[bench] -fn bench_push_str_one_byte(b: &mut Bencher) { - b.bytes = REPETITIONS; - b.iter(|| { - let mut r = String::new(); - for _ in 0..REPETITIONS { - r.push_str("a") - } - }); -} - -#[bench] -fn bench_push_char_one_byte(b: &mut Bencher) { - b.bytes = REPETITIONS; - b.iter(|| { - let mut r = String::new(); - for _ in 0..REPETITIONS { - r.push('a') - } - }); -} - -#[bench] -fn bench_push_char_two_bytes(b: &mut Bencher) { - b.bytes = REPETITIONS * 2; - b.iter(|| { - let mut r = String::new(); - for _ in 0..REPETITIONS { - r.push('â') - } - }); -} - -#[bench] -fn from_utf8_lossy_100_ascii(b: &mut Bencher) { - let s = b"Hello there, the quick brown fox jumped over the lazy dog! \ - Lorem ipsum dolor sit amet, consectetur. "; - - assert_eq!(100, s.len()); - b.iter(|| { - let _ = String::from_utf8_lossy(s); - }); -} - -#[bench] -fn from_utf8_lossy_100_multibyte(b: &mut Bencher) { - let s = "𐌀𐌖𐌋𐌄𐌑𐌉ปรدولة الكويتทศไทย中华𐍅𐌿𐌻𐍆𐌹𐌻𐌰".as_bytes(); - assert_eq!(100, s.len()); - b.iter(|| { - let _ = String::from_utf8_lossy(s); - }); -} - -#[bench] -fn from_utf8_lossy_invalid(b: &mut Bencher) { - let s = b"Hello\xC0\x80 There\xE6\x83 Goodbye"; - b.iter(|| { - let _ = String::from_utf8_lossy(s); - }); -} - -#[bench] -fn from_utf8_lossy_100_invalid(b: &mut Bencher) { - let s = repeat(0xf5).take(100).collect::<Vec<_>>(); - b.iter(|| { - let _ = String::from_utf8_lossy(&s); - }); -} - -#[bench] -fn bench_exact_size_shrink_to_fit(b: &mut Bencher) { - let s = "Hello there, the quick brown fox jumped over the lazy dog! \ - Lorem ipsum dolor sit amet, consectetur. "; - // ensure our operation produces an exact-size string before we benchmark it - let mut r = String::with_capacity(s.len()); - r.push_str(s); - assert_eq!(r.len(), r.capacity()); - b.iter(|| { - let mut r = String::with_capacity(s.len()); - r.push_str(s); - r.shrink_to_fit(); - r - }); -} - -#[bench] -fn bench_from_str(b: &mut Bencher) { - let s = "Hello there, the quick brown fox jumped over the lazy dog! \ - Lorem ipsum dolor sit amet, consectetur. "; - b.iter(|| String::from(s)) -} - -#[bench] -fn bench_from(b: &mut Bencher) { - let s = "Hello there, the quick brown fox jumped over the lazy dog! \ - Lorem ipsum dolor sit amet, consectetur. "; - b.iter(|| String::from(s)) -} - -#[bench] -fn bench_to_string(b: &mut Bencher) { - let s = "Hello there, the quick brown fox jumped over the lazy dog! \ - Lorem ipsum dolor sit amet, consectetur. "; - b.iter(|| s.to_string()) -} - -#[bench] -fn bench_insert_char_short(b: &mut Bencher) { - let s = "Hello, World!"; - b.iter(|| { - let mut x = String::from(s); - black_box(&mut x).insert(6, black_box(' ')); - x - }) -} - -#[bench] -fn bench_insert_char_long(b: &mut Bencher) { - let s = "Hello, World!"; - b.iter(|| { - let mut x = String::from(s); - black_box(&mut x).insert(6, black_box('❤')); - x - }) -} - -#[bench] -fn bench_insert_str_short(b: &mut Bencher) { - let s = "Hello, World!"; - b.iter(|| { - let mut x = String::from(s); - black_box(&mut x).insert_str(6, black_box(" ")); - x - }) -} - -#[bench] -fn bench_insert_str_long(b: &mut Bencher) { - let s = "Hello, World!"; - b.iter(|| { - let mut x = String::from(s); - black_box(&mut x).insert_str(6, black_box(" rustic ")); - x - }) -} diff --git a/library/alloc/benches/vec.rs b/library/alloc/benches/vec.rs deleted file mode 100644 index 1dab71fa1f4..00000000000 --- a/library/alloc/benches/vec.rs +++ /dev/null @@ -1,878 +0,0 @@ -use std::iter::repeat; - -use rand::RngCore; -use test::{Bencher, black_box}; - -#[bench] -fn bench_new(b: &mut Bencher) { - b.iter(|| Vec::<u32>::new()) -} - -fn do_bench_with_capacity(b: &mut Bencher, src_len: usize) { - b.bytes = src_len as u64; - - b.iter(|| Vec::<u32>::with_capacity(src_len)) -} - -#[bench] -fn bench_with_capacity_0000(b: &mut Bencher) { - do_bench_with_capacity(b, 0) -} - -#[bench] -fn bench_with_capacity_0010(b: &mut Bencher) { - do_bench_with_capacity(b, 10) -} - -#[bench] -fn bench_with_capacity_0100(b: &mut Bencher) { - do_bench_with_capacity(b, 100) -} - -#[bench] -fn bench_with_capacity_1000(b: &mut Bencher) { - do_bench_with_capacity(b, 1000) -} - -fn do_bench_from_fn(b: &mut Bencher, src_len: usize) { - b.bytes = src_len as u64; - - b.iter(|| (0..src_len).collect::<Vec<_>>()) -} - -#[bench] -fn bench_from_fn_0000(b: &mut Bencher) { - do_bench_from_fn(b, 0) -} - -#[bench] -fn bench_from_fn_0010(b: &mut Bencher) { - do_bench_from_fn(b, 10) -} - -#[bench] -fn bench_from_fn_0100(b: &mut Bencher) { - do_bench_from_fn(b, 100) -} - -#[bench] -fn bench_from_fn_1000(b: &mut Bencher) { - do_bench_from_fn(b, 1000) -} - -fn do_bench_from_elem(b: &mut Bencher, src_len: usize) { - b.bytes = src_len as u64; - - b.iter(|| repeat(5).take(src_len).collect::<Vec<usize>>()) -} - -#[bench] -fn bench_from_elem_0000(b: &mut Bencher) { - do_bench_from_elem(b, 0) -} - -#[bench] -fn bench_from_elem_0010(b: &mut Bencher) { - do_bench_from_elem(b, 10) -} - -#[bench] -fn bench_from_elem_0100(b: &mut Bencher) { - do_bench_from_elem(b, 100) -} - -#[bench] -fn bench_from_elem_1000(b: &mut Bencher) { - do_bench_from_elem(b, 1000) -} - -fn do_bench_from_slice(b: &mut Bencher, src_len: usize) { - let src: Vec<_> = FromIterator::from_iter(0..src_len); - - b.bytes = src_len as u64; - - b.iter(|| src.as_slice().to_vec()); -} - -#[bench] -fn bench_from_slice_0000(b: &mut Bencher) { - do_bench_from_slice(b, 0) -} - -#[bench] -fn bench_from_slice_0010(b: &mut Bencher) { - do_bench_from_slice(b, 10) -} - -#[bench] -fn bench_from_slice_0100(b: &mut Bencher) { - do_bench_from_slice(b, 100) -} - -#[bench] -fn bench_from_slice_1000(b: &mut Bencher) { - do_bench_from_slice(b, 1000) -} - -fn do_bench_from_iter(b: &mut Bencher, src_len: usize) { - let src: Vec<_> = FromIterator::from_iter(0..src_len); - - b.bytes = src_len as u64; - - b.iter(|| { - let dst: Vec<_> = FromIterator::from_iter(src.iter().cloned()); - dst - }); -} - -#[bench] -fn bench_from_iter_0000(b: &mut Bencher) { - do_bench_from_iter(b, 0) -} - -#[bench] -fn bench_from_iter_0010(b: &mut Bencher) { - do_bench_from_iter(b, 10) -} - -#[bench] -fn bench_from_iter_0100(b: &mut Bencher) { - do_bench_from_iter(b, 100) -} - -#[bench] -fn bench_from_iter_1000(b: &mut Bencher) { - do_bench_from_iter(b, 1000) -} - -fn do_bench_extend(b: &mut Bencher, dst_len: usize, src_len: usize) { - let dst: Vec<_> = FromIterator::from_iter(0..dst_len); - let src: Vec<_> = FromIterator::from_iter(dst_len..dst_len + src_len); - - b.bytes = src_len as u64; - - b.iter(|| { - let mut dst = dst.clone(); - dst.extend(src.clone()); - dst - }); -} - -#[bench] -fn bench_extend_0000_0000(b: &mut Bencher) { - do_bench_extend(b, 0, 0) -} - -#[bench] -fn bench_extend_0000_0010(b: &mut Bencher) { - do_bench_extend(b, 0, 10) -} - -#[bench] -fn bench_extend_0000_0100(b: &mut Bencher) { - do_bench_extend(b, 0, 100) -} - -#[bench] -fn bench_extend_0000_1000(b: &mut Bencher) { - do_bench_extend(b, 0, 1000) -} - -#[bench] -fn bench_extend_0010_0010(b: &mut Bencher) { - do_bench_extend(b, 10, 10) -} - -#[bench] -fn bench_extend_0100_0100(b: &mut Bencher) { - do_bench_extend(b, 100, 100) -} - -#[bench] -fn bench_extend_1000_1000(b: &mut Bencher) { - do_bench_extend(b, 1000, 1000) -} - -fn do_bench_extend_from_slice(b: &mut Bencher, dst_len: usize, src_len: usize) { - let dst: Vec<_> = FromIterator::from_iter(0..dst_len); - let src: Vec<_> = FromIterator::from_iter(dst_len..dst_len + src_len); - - b.bytes = src_len as u64; - - b.iter(|| { - let mut dst = dst.clone(); - dst.extend_from_slice(&src); - dst - }); -} - -#[bench] -fn bench_extend_recycle(b: &mut Bencher) { - let mut data = vec![0; 1000]; - - b.iter(|| { - let tmp = std::mem::take(&mut data); - let mut to_extend = black_box(Vec::new()); - to_extend.extend(tmp.into_iter()); - data = black_box(to_extend); - }); - - black_box(data); -} - -#[bench] -fn bench_extend_from_slice_0000_0000(b: &mut Bencher) { - do_bench_extend_from_slice(b, 0, 0) -} - -#[bench] -fn bench_extend_from_slice_0000_0010(b: &mut Bencher) { - do_bench_extend_from_slice(b, 0, 10) -} - -#[bench] -fn bench_extend_from_slice_0000_0100(b: &mut Bencher) { - do_bench_extend_from_slice(b, 0, 100) -} - -#[bench] -fn bench_extend_from_slice_0000_1000(b: &mut Bencher) { - do_bench_extend_from_slice(b, 0, 1000) -} - -#[bench] -fn bench_extend_from_slice_0010_0010(b: &mut Bencher) { - do_bench_extend_from_slice(b, 10, 10) -} - -#[bench] -fn bench_extend_from_slice_0100_0100(b: &mut Bencher) { - do_bench_extend_from_slice(b, 100, 100) -} - -#[bench] -fn bench_extend_from_slice_1000_1000(b: &mut Bencher) { - do_bench_extend_from_slice(b, 1000, 1000) -} - -fn do_bench_clone(b: &mut Bencher, src_len: usize) { - let src: Vec<usize> = FromIterator::from_iter(0..src_len); - - b.bytes = src_len as u64; - - b.iter(|| src.clone()); -} - -#[bench] -fn bench_clone_0000(b: &mut Bencher) { - do_bench_clone(b, 0) -} - -#[bench] -fn bench_clone_0010(b: &mut Bencher) { - do_bench_clone(b, 10) -} - -#[bench] -fn bench_clone_0100(b: &mut Bencher) { - do_bench_clone(b, 100) -} - -#[bench] -fn bench_clone_1000(b: &mut Bencher) { - do_bench_clone(b, 1000) -} - -fn do_bench_clone_from(b: &mut Bencher, times: usize, dst_len: usize, src_len: usize) { - let dst: Vec<_> = FromIterator::from_iter(0..src_len); - let src: Vec<_> = FromIterator::from_iter(dst_len..dst_len + src_len); - - b.bytes = (times * src_len) as u64; - - b.iter(|| { - let mut dst = dst.clone(); - - for _ in 0..times { - dst.clone_from(&src); - dst = black_box(dst); - } - dst - }); -} - -#[bench] -fn bench_clone_from_01_0000_0000(b: &mut Bencher) { - do_bench_clone_from(b, 1, 0, 0) -} - -#[bench] -fn bench_clone_from_01_0000_0010(b: &mut Bencher) { - do_bench_clone_from(b, 1, 0, 10) -} - -#[bench] -fn bench_clone_from_01_0000_0100(b: &mut Bencher) { - do_bench_clone_from(b, 1, 0, 100) -} - -#[bench] -fn bench_clone_from_01_0000_1000(b: &mut Bencher) { - do_bench_clone_from(b, 1, 0, 1000) -} - -#[bench] -fn bench_clone_from_01_0010_0010(b: &mut Bencher) { - do_bench_clone_from(b, 1, 10, 10) -} - -#[bench] -fn bench_clone_from_01_0100_0100(b: &mut Bencher) { - do_bench_clone_from(b, 1, 100, 100) -} - -#[bench] -fn bench_clone_from_01_1000_1000(b: &mut Bencher) { - do_bench_clone_from(b, 1, 1000, 1000) -} - -#[bench] -fn bench_clone_from_01_0010_0100(b: &mut Bencher) { - do_bench_clone_from(b, 1, 10, 100) -} - -#[bench] -fn bench_clone_from_01_0100_1000(b: &mut Bencher) { - do_bench_clone_from(b, 1, 100, 1000) -} - -#[bench] -fn bench_clone_from_01_0010_0000(b: &mut Bencher) { - do_bench_clone_from(b, 1, 10, 0) -} - -#[bench] -fn bench_clone_from_01_0100_0010(b: &mut Bencher) { - do_bench_clone_from(b, 1, 100, 10) -} - -#[bench] -fn bench_clone_from_01_1000_0100(b: &mut Bencher) { - do_bench_clone_from(b, 1, 1000, 100) -} - -#[bench] -fn bench_clone_from_10_0000_0000(b: &mut Bencher) { - do_bench_clone_from(b, 10, 0, 0) -} - -#[bench] -fn bench_clone_from_10_0000_0010(b: &mut Bencher) { - do_bench_clone_from(b, 10, 0, 10) -} - -#[bench] -fn bench_clone_from_10_0000_0100(b: &mut Bencher) { - do_bench_clone_from(b, 10, 0, 100) -} - -#[bench] -fn bench_clone_from_10_0000_1000(b: &mut Bencher) { - do_bench_clone_from(b, 10, 0, 1000) -} - -#[bench] -fn bench_clone_from_10_0010_0010(b: &mut Bencher) { - do_bench_clone_from(b, 10, 10, 10) -} - -#[bench] -fn bench_clone_from_10_0100_0100(b: &mut Bencher) { - do_bench_clone_from(b, 10, 100, 100) -} - -#[bench] -fn bench_clone_from_10_1000_1000(b: &mut Bencher) { - do_bench_clone_from(b, 10, 1000, 1000) -} - -#[bench] -fn bench_clone_from_10_0010_0100(b: &mut Bencher) { - do_bench_clone_from(b, 10, 10, 100) -} - -#[bench] -fn bench_clone_from_10_0100_1000(b: &mut Bencher) { - do_bench_clone_from(b, 10, 100, 1000) -} - -#[bench] -fn bench_clone_from_10_0010_0000(b: &mut Bencher) { - do_bench_clone_from(b, 10, 10, 0) -} - -#[bench] -fn bench_clone_from_10_0100_0010(b: &mut Bencher) { - do_bench_clone_from(b, 10, 100, 10) -} - -#[bench] -fn bench_clone_from_10_1000_0100(b: &mut Bencher) { - do_bench_clone_from(b, 10, 1000, 100) -} - -macro_rules! bench_in_place { - ($($fname:ident, $type:ty, $count:expr, $init:expr);*) => { - $( - #[bench] - fn $fname(b: &mut Bencher) { - b.iter(|| { - let src: Vec<$type> = black_box(vec![$init; $count]); - src.into_iter() - .enumerate() - .map(|(idx, e)| idx as $type ^ e) - .collect::<Vec<$type>>() - }); - } - )+ - }; -} - -bench_in_place![ - bench_in_place_xxu8_0010_i0, u8, 10, 0; - bench_in_place_xxu8_0100_i0, u8, 100, 0; - bench_in_place_xxu8_1000_i0, u8, 1000, 0; - bench_in_place_xxu8_0010_i1, u8, 10, 1; - bench_in_place_xxu8_0100_i1, u8, 100, 1; - bench_in_place_xxu8_1000_i1, u8, 1000, 1; - bench_in_place_xu32_0010_i0, u32, 10, 0; - bench_in_place_xu32_0100_i0, u32, 100, 0; - bench_in_place_xu32_1000_i0, u32, 1000, 0; - bench_in_place_xu32_0010_i1, u32, 10, 1; - bench_in_place_xu32_0100_i1, u32, 100, 1; - bench_in_place_xu32_1000_i1, u32, 1000, 1; - bench_in_place_u128_0010_i0, u128, 10, 0; - bench_in_place_u128_0100_i0, u128, 100, 0; - bench_in_place_u128_1000_i0, u128, 1000, 0; - bench_in_place_u128_0010_i1, u128, 10, 1; - bench_in_place_u128_0100_i1, u128, 100, 1; - bench_in_place_u128_1000_i1, u128, 1000, 1 -]; - -#[bench] -fn bench_in_place_recycle(b: &mut Bencher) { - let mut data = vec![0; 1000]; - - b.iter(|| { - let tmp = std::mem::take(&mut data); - data = black_box( - tmp.into_iter() - .enumerate() - .map(|(idx, e)| idx.wrapping_add(e)) - .fuse() - .collect::<Vec<usize>>(), - ); - }); -} - -#[bench] -fn bench_in_place_zip_recycle(b: &mut Bencher) { - let mut data = vec![0u8; 1000]; - let mut rng = crate::bench_rng(); - let mut subst = vec![0u8; 1000]; - rng.fill_bytes(&mut subst[..]); - - b.iter(|| { - let tmp = std::mem::take(&mut data); - let mangled = tmp - .into_iter() - .zip(subst.iter().copied()) - .enumerate() - .map(|(i, (d, s))| d.wrapping_add(i as u8) ^ s) - .collect::<Vec<_>>(); - data = black_box(mangled); - }); -} - -#[bench] -fn bench_in_place_zip_iter_mut(b: &mut Bencher) { - let mut data = vec![0u8; 256]; - let mut rng = crate::bench_rng(); - let mut subst = vec![0u8; 1000]; - rng.fill_bytes(&mut subst[..]); - - b.iter(|| { - data.iter_mut().enumerate().for_each(|(i, d)| { - *d = d.wrapping_add(i as u8) ^ subst[i]; - }); - }); - - black_box(data); -} - -pub fn vec_cast<T, U>(input: Vec<T>) -> Vec<U> { - input.into_iter().map(|e| unsafe { std::mem::transmute_copy(&e) }).collect() -} - -#[bench] -fn bench_transmute(b: &mut Bencher) { - let mut vec = vec![10u32; 100]; - b.bytes = 800; // 2 casts x 4 bytes x 100 - b.iter(|| { - let v = std::mem::take(&mut vec); - let v = black_box(vec_cast::<u32, i32>(v)); - let v = black_box(vec_cast::<i32, u32>(v)); - vec = v; - }); -} - -#[derive(Clone)] -struct Droppable(usize); - -impl Drop for Droppable { - fn drop(&mut self) { - black_box(self); - } -} - -#[bench] -fn bench_in_place_collect_droppable(b: &mut Bencher) { - let v: Vec<Droppable> = std::iter::repeat_with(|| Droppable(0)).take(1000).collect(); - b.iter(|| { - v.clone() - .into_iter() - .skip(100) - .enumerate() - .map(|(i, e)| Droppable(i ^ e.0)) - .collect::<Vec<_>>() - }) -} - -// node.js gives out of memory error to use with length 1_100_000 -#[cfg(target_os = "emscripten")] -const LEN: usize = 4096; - -#[cfg(not(target_os = "emscripten"))] -const LEN: usize = 16384; - -#[bench] -fn bench_chain_collect(b: &mut Bencher) { - let data = black_box([0; LEN]); - b.iter(|| data.iter().cloned().chain([1]).collect::<Vec<_>>()); -} - -#[bench] -fn bench_chain_chain_collect(b: &mut Bencher) { - let data = black_box([0; LEN]); - b.iter(|| data.iter().cloned().chain([1]).chain([2]).collect::<Vec<_>>()); -} - -#[bench] -fn bench_nest_chain_chain_collect(b: &mut Bencher) { - let data = black_box([0; LEN]); - b.iter(|| { - data.iter().cloned().chain([1].iter().chain([2].iter()).cloned()).collect::<Vec<_>>() - }); -} - -#[bench] -fn bench_range_map_collect(b: &mut Bencher) { - b.iter(|| (0..LEN).map(|_| u32::default()).collect::<Vec<_>>()); -} - -#[bench] -fn bench_chain_extend_ref(b: &mut Bencher) { - let data = black_box([0; LEN]); - b.iter(|| { - let mut v = Vec::<u32>::with_capacity(data.len() + 1); - v.extend(data.iter().chain([1].iter())); - v - }); -} - -#[bench] -fn bench_chain_extend_value(b: &mut Bencher) { - let data = black_box([0; LEN]); - b.iter(|| { - let mut v = Vec::<u32>::with_capacity(data.len() + 1); - v.extend(data.iter().cloned().chain(Some(1))); - v - }); -} - -#[bench] -fn bench_rev_1(b: &mut Bencher) { - let data = black_box([0; LEN]); - b.iter(|| { - let mut v = Vec::<u32>::new(); - v.extend(data.iter().rev()); - v - }); -} - -#[bench] -fn bench_rev_2(b: &mut Bencher) { - let data = black_box([0; LEN]); - b.iter(|| { - let mut v = Vec::<u32>::with_capacity(data.len()); - v.extend(data.iter().rev()); - v - }); -} - -#[bench] -fn bench_map_regular(b: &mut Bencher) { - let data = black_box([(0, 0); LEN]); - b.iter(|| { - let mut v = Vec::<u32>::new(); - v.extend(data.iter().map(|t| t.1)); - v - }); -} - -#[bench] -fn bench_map_fast(b: &mut Bencher) { - let data = black_box([(0, 0); LEN]); - b.iter(|| { - let mut result: Vec<u32> = Vec::with_capacity(data.len()); - for i in 0..data.len() { - unsafe { - *result.as_mut_ptr().add(i) = data[i].0; - result.set_len(i); - } - } - result - }); -} - -fn random_sorted_fill(mut seed: u32, buf: &mut [u32]) { - let mask = if buf.len() < 8192 { - 0xFF - } else if buf.len() < 200_000 { - 0xFFFF - } else { - 0xFFFF_FFFF - }; - - for item in buf.iter_mut() { - seed ^= seed << 13; - seed ^= seed >> 17; - seed ^= seed << 5; - - *item = seed & mask; - } - - buf.sort(); -} - -// Measures performance of slice dedup impl. -// This was used to justify separate implementation of dedup for Vec. -// This algorithm was used for Vecs prior to Rust 1.52. -fn bench_dedup_slice_truncate(b: &mut Bencher, sz: usize) { - let mut template = vec![0u32; sz]; - b.bytes = size_of_val(template.as_slice()) as u64; - random_sorted_fill(0x43, &mut template); - - let mut vec = template.clone(); - b.iter(|| { - let vec = black_box(&mut vec); - let len = { - let (dedup, _) = vec.partition_dedup(); - dedup.len() - }; - vec.truncate(len); - - black_box(vec.first()); - let vec = black_box(vec); - vec.clear(); - vec.extend_from_slice(&template); - }); -} - -// Measures performance of Vec::dedup on random data. -fn bench_vec_dedup_random(b: &mut Bencher, sz: usize) { - let mut template = vec![0u32; sz]; - b.bytes = size_of_val(template.as_slice()) as u64; - random_sorted_fill(0x43, &mut template); - - let mut vec = template.clone(); - b.iter(|| { - let vec = black_box(&mut vec); - vec.dedup(); - black_box(vec.first()); - let vec = black_box(vec); - vec.clear(); - vec.extend_from_slice(&template); - }); -} - -// Measures performance of Vec::dedup when there is no items removed -fn bench_vec_dedup_none(b: &mut Bencher, sz: usize) { - let mut template = vec![0u32; sz]; - b.bytes = size_of_val(template.as_slice()) as u64; - template.chunks_exact_mut(2).for_each(|w| { - w[0] = black_box(0); - w[1] = black_box(5); - }); - - let mut vec = template.clone(); - b.iter(|| { - let vec = black_box(&mut vec); - vec.dedup(); - black_box(vec.first()); - // Unlike other benches of `dedup` - // this doesn't reinitialize vec - // because we measure how efficient dedup is - // when no memory written - }); -} - -// Measures performance of Vec::dedup when there is all items removed -fn bench_vec_dedup_all(b: &mut Bencher, sz: usize) { - let mut template = vec![0u32; sz]; - b.bytes = size_of_val(template.as_slice()) as u64; - template.iter_mut().for_each(|w| { - *w = black_box(0); - }); - - let mut vec = template.clone(); - b.iter(|| { - let vec = black_box(&mut vec); - vec.dedup(); - black_box(vec.first()); - let vec = black_box(vec); - vec.clear(); - vec.extend_from_slice(&template); - }); -} - -#[bench] -fn bench_dedup_slice_truncate_100(b: &mut Bencher) { - bench_dedup_slice_truncate(b, 100); -} -#[bench] -fn bench_dedup_random_100(b: &mut Bencher) { - bench_vec_dedup_random(b, 100); -} - -#[bench] -fn bench_dedup_none_100(b: &mut Bencher) { - bench_vec_dedup_none(b, 100); -} - -#[bench] -fn bench_dedup_all_100(b: &mut Bencher) { - bench_vec_dedup_all(b, 100); -} - -#[bench] -fn bench_dedup_slice_truncate_1000(b: &mut Bencher) { - bench_dedup_slice_truncate(b, 1000); -} -#[bench] -fn bench_dedup_random_1000(b: &mut Bencher) { - bench_vec_dedup_random(b, 1000); -} - -#[bench] -fn bench_dedup_none_1000(b: &mut Bencher) { - bench_vec_dedup_none(b, 1000); -} - -#[bench] -fn bench_dedup_all_1000(b: &mut Bencher) { - bench_vec_dedup_all(b, 1000); -} - -#[bench] -fn bench_dedup_slice_truncate_10000(b: &mut Bencher) { - bench_dedup_slice_truncate(b, 10000); -} -#[bench] -fn bench_dedup_random_10000(b: &mut Bencher) { - bench_vec_dedup_random(b, 10000); -} - -#[bench] -fn bench_dedup_none_10000(b: &mut Bencher) { - bench_vec_dedup_none(b, 10000); -} - -#[bench] -fn bench_dedup_all_10000(b: &mut Bencher) { - bench_vec_dedup_all(b, 10000); -} - -#[bench] -fn bench_dedup_slice_truncate_100000(b: &mut Bencher) { - bench_dedup_slice_truncate(b, 100000); -} -#[bench] -fn bench_dedup_random_100000(b: &mut Bencher) { - bench_vec_dedup_random(b, 100000); -} - -#[bench] -fn bench_dedup_none_100000(b: &mut Bencher) { - bench_vec_dedup_none(b, 100000); -} - -#[bench] -fn bench_dedup_all_100000(b: &mut Bencher) { - bench_vec_dedup_all(b, 100000); -} - -#[bench] -fn bench_flat_map_collect(b: &mut Bencher) { - let v = vec![777u32; 500000]; - b.iter(|| v.iter().flat_map(|color| color.rotate_left(8).to_be_bytes()).collect::<Vec<_>>()); -} - -/// Reference benchmark that `retain` has to compete with. -#[bench] -fn bench_retain_iter_100000(b: &mut Bencher) { - let mut v = Vec::with_capacity(100000); - - b.iter(|| { - let mut tmp = std::mem::take(&mut v); - tmp.clear(); - tmp.extend(black_box(1..=100000)); - v = tmp.into_iter().filter(|x| x & 1 == 0).collect(); - }); -} - -#[bench] -fn bench_retain_100000(b: &mut Bencher) { - let mut v = Vec::with_capacity(100000); - - b.iter(|| { - v.clear(); - v.extend(black_box(1..=100000)); - v.retain(|x| x & 1 == 0) - }); -} - -#[bench] -fn bench_retain_whole_100000(b: &mut Bencher) { - let mut v = black_box(vec![826u32; 100000]); - b.iter(|| v.retain(|x| *x == 826u32)); -} - -#[bench] -fn bench_next_chunk(b: &mut Bencher) { - let v = vec![13u8; 2048]; - - b.iter(|| { - const CHUNK: usize = 8; - - let mut sum = [0u32; CHUNK]; - let mut iter = black_box(v.clone()).into_iter(); - - while let Ok(chunk) = iter.next_chunk::<CHUNK>() { - for i in 0..CHUNK { - sum[i] += chunk[i] as u32; - } - } - - sum - }) -} diff --git a/library/alloc/benches/vec_deque.rs b/library/alloc/benches/vec_deque.rs deleted file mode 100644 index a56f8496963..00000000000 --- a/library/alloc/benches/vec_deque.rs +++ /dev/null @@ -1,267 +0,0 @@ -use std::collections::{VecDeque, vec_deque}; -use std::mem; - -use test::{Bencher, black_box}; - -#[bench] -fn bench_new(b: &mut Bencher) { - b.iter(|| { - let ring: VecDeque<i32> = VecDeque::new(); - black_box(ring); - }) -} - -#[bench] -fn bench_grow_1025(b: &mut Bencher) { - b.iter(|| { - let mut deq = VecDeque::new(); - for i in 0..1025 { - deq.push_front(i); - } - black_box(deq); - }) -} - -#[bench] -fn bench_iter_1000(b: &mut Bencher) { - let ring: VecDeque<_> = (0..1000).collect(); - - b.iter(|| { - let mut sum = 0; - for &i in &ring { - sum += i; - } - black_box(sum); - }) -} - -#[bench] -fn bench_mut_iter_1000(b: &mut Bencher) { - let mut ring: VecDeque<_> = (0..1000).collect(); - - b.iter(|| { - let mut sum = 0; - for i in &mut ring { - sum += *i; - } - black_box(sum); - }) -} - -#[bench] -fn bench_try_fold(b: &mut Bencher) { - let ring: VecDeque<_> = (0..1000).collect(); - - b.iter(|| black_box(ring.iter().try_fold(0, |a, b| Some(a + b)))) -} - -/// does the memory bookkeeping to reuse the buffer of the Vec between iterations. -/// `setup` must not modify its argument's length or capacity. `g` must not move out of its argument. -fn into_iter_helper< - T: Copy, - F: FnOnce(&mut VecDeque<T>), - G: FnOnce(&mut vec_deque::IntoIter<T>), ->( - v: &mut Vec<T>, - setup: F, - g: G, -) { - let ptr = v.as_mut_ptr(); - let len = v.len(); - // ensure that the vec is full, to make sure that any wrapping from the deque doesn't - // access uninitialized memory. - assert_eq!(v.len(), v.capacity()); - - let mut deque = VecDeque::from(mem::take(v)); - setup(&mut deque); - - let mut it = deque.into_iter(); - g(&mut it); - - mem::forget(it); - - // SAFETY: the provided functions are not allowed to modify the allocation, so the buffer is still alive. - // len and capacity are accurate due to the above assertion. - // All the elements in the buffer are still valid, because of `T: Copy` which implies `T: !Drop`. - mem::forget(mem::replace(v, unsafe { Vec::from_raw_parts(ptr, len, len) })); -} - -#[bench] -fn bench_into_iter(b: &mut Bencher) { - let len = 1024; - // we reuse this allocation for every run - let mut vec: Vec<usize> = (0..len).collect(); - vec.shrink_to_fit(); - - b.iter(|| { - let mut sum = 0; - into_iter_helper( - &mut vec, - |_| {}, - |it| { - for i in it { - sum += i; - } - }, - ); - black_box(sum); - - let mut sum = 0; - // rotating a full deque doesn't move any memory. - into_iter_helper( - &mut vec, - |d| d.rotate_left(len / 2), - |it| { - for i in it { - sum += i; - } - }, - ); - black_box(sum); - }); -} - -#[bench] -fn bench_into_iter_fold(b: &mut Bencher) { - let len = 1024; - - // because `fold` takes ownership of the iterator, - // we can't prevent it from dropping the memory, - // so we have to bite the bullet and reallocate - // for every iteration. - b.iter(|| { - let deque: VecDeque<usize> = (0..len).collect(); - assert_eq!(deque.len(), deque.capacity()); - let sum = deque.into_iter().fold(0, |a, b| a + b); - black_box(sum); - - // rotating a full deque doesn't move any memory. - let mut deque: VecDeque<usize> = (0..len).collect(); - assert_eq!(deque.len(), deque.capacity()); - deque.rotate_left(len / 2); - let sum = deque.into_iter().fold(0, |a, b| a + b); - black_box(sum); - }); -} - -#[bench] -fn bench_into_iter_try_fold(b: &mut Bencher) { - let len = 1024; - // we reuse this allocation for every run - let mut vec: Vec<usize> = (0..len).collect(); - vec.shrink_to_fit(); - - // Iterator::any uses Iterator::try_fold under the hood - b.iter(|| { - let mut b = false; - into_iter_helper(&mut vec, |_| {}, |it| b = it.any(|i| i == len - 1)); - black_box(b); - - into_iter_helper(&mut vec, |d| d.rotate_left(len / 2), |it| b = it.any(|i| i == len - 1)); - black_box(b); - }); -} - -#[bench] -fn bench_into_iter_next_chunk(b: &mut Bencher) { - let len = 1024; - // we reuse this allocation for every run - let mut vec: Vec<usize> = (0..len).collect(); - vec.shrink_to_fit(); - - b.iter(|| { - let mut buf = [0; 64]; - into_iter_helper( - &mut vec, - |_| {}, - |it| { - while let Ok(a) = it.next_chunk() { - buf = a; - } - }, - ); - black_box(buf); - - into_iter_helper( - &mut vec, - |d| d.rotate_left(len / 2), - |it| { - while let Ok(a) = it.next_chunk() { - buf = a; - } - }, - ); - black_box(buf); - }); -} - -#[bench] -fn bench_from_array_1000(b: &mut Bencher) { - const N: usize = 1000; - let mut array: [usize; N] = [0; N]; - - for i in 0..N { - array[i] = i; - } - - b.iter(|| { - let deq: VecDeque<_> = array.into(); - black_box(deq); - }) -} - -#[bench] -fn bench_extend_bytes(b: &mut Bencher) { - let mut ring: VecDeque<u8> = VecDeque::with_capacity(1000); - let input: &[u8] = &[128; 512]; - - b.iter(|| { - ring.clear(); - ring.extend(black_box(input)); - }); -} - -#[bench] -fn bench_extend_vec(b: &mut Bencher) { - let mut ring: VecDeque<u8> = VecDeque::with_capacity(1000); - let input = vec![128; 512]; - - b.iter(|| { - ring.clear(); - - let input = input.clone(); - ring.extend(black_box(input)); - }); -} - -#[bench] -fn bench_extend_trustedlen(b: &mut Bencher) { - let mut ring: VecDeque<u16> = VecDeque::with_capacity(1000); - - b.iter(|| { - ring.clear(); - ring.extend(black_box(0..512)); - }); -} - -#[bench] -fn bench_extend_chained_trustedlen(b: &mut Bencher) { - let mut ring: VecDeque<u16> = VecDeque::with_capacity(1000); - - b.iter(|| { - ring.clear(); - ring.extend(black_box((0..256).chain(768..1024))); - }); -} - -#[bench] -fn bench_extend_chained_bytes(b: &mut Bencher) { - let mut ring: VecDeque<u16> = VecDeque::with_capacity(1000); - let input1: &[u16] = &[128; 256]; - let input2: &[u16] = &[255; 256]; - - b.iter(|| { - ring.clear(); - ring.extend(black_box(input1.iter().chain(input2.iter()))); - }); -} diff --git a/library/alloc/benches/vec_deque_append.rs b/library/alloc/benches/vec_deque_append.rs deleted file mode 100644 index 7c805da9737..00000000000 --- a/library/alloc/benches/vec_deque_append.rs +++ /dev/null @@ -1,40 +0,0 @@ -use std::collections::VecDeque; -use std::time::Instant; - -const VECDEQUE_LEN: i32 = 100000; -const WARMUP_N: usize = 100; -const BENCH_N: usize = 1000; - -fn main() { - if cfg!(miri) { - // Don't benchmark Miri... - // (Due to bootstrap quirks, this gets picked up by `x.py miri library/alloc --no-doc`.) - return; - } - let a: VecDeque<i32> = (0..VECDEQUE_LEN).collect(); - let b: VecDeque<i32> = (0..VECDEQUE_LEN).collect(); - - for _ in 0..WARMUP_N { - let mut c = a.clone(); - let mut d = b.clone(); - c.append(&mut d); - } - - let mut durations = Vec::with_capacity(BENCH_N); - - for _ in 0..BENCH_N { - let mut c = a.clone(); - let mut d = b.clone(); - let before = Instant::now(); - c.append(&mut d); - let after = Instant::now(); - durations.push(after.duration_since(before)); - } - - let l = durations.len(); - durations.sort(); - - assert!(BENCH_N % 2 == 0); - let median = (durations[(l / 2) - 1] + durations[l / 2]) / 2; - println!("\ncustom-bench vec_deque_append {:?} ns/iter\n", median.as_nanos()); -} diff --git a/library/alloc/src/alloc.rs b/library/alloc/src/alloc.rs index 3bfdc68dcda..2f752f6eb39 100644 --- a/library/alloc/src/alloc.rs +++ b/library/alloc/src/alloc.rs @@ -5,9 +5,7 @@ #[stable(feature = "alloc_module", since = "1.28.0")] #[doc(inline)] pub use core::alloc::*; -#[cfg(not(test))] use core::hint; -#[cfg(not(test))] use core::ptr::{self, NonNull}; unsafe extern "Rust" { @@ -44,14 +42,10 @@ unsafe extern "Rust" { /// accessed through the [free functions in `alloc`](self#functions). #[unstable(feature = "allocator_api", issue = "32838")] #[derive(Copy, Clone, Default, Debug)] -#[cfg(not(test))] // the compiler needs to know when a Box uses the global allocator vs a custom one #[lang = "global_alloc_ty"] pub struct Global; -#[cfg(test)] -pub use std::alloc::Global; - /// Allocates memory with the global allocator. /// /// This function forwards calls to the [`GlobalAlloc::alloc`] method @@ -180,7 +174,6 @@ pub unsafe fn alloc_zeroed(layout: Layout) -> *mut u8 { } } -#[cfg(not(test))] impl Global { #[inline] #[cfg_attr(miri, track_caller)] // even without panics, this helps for Miri backtraces @@ -246,7 +239,6 @@ impl Global { } #[unstable(feature = "allocator_api", issue = "32838")] -#[cfg(not(test))] unsafe impl Allocator for Global { #[inline] #[cfg_attr(miri, track_caller)] // even without panics, this helps for Miri backtraces @@ -346,7 +338,7 @@ unsafe impl Allocator for Global { } /// The allocator for `Box`. -#[cfg(all(not(no_global_oom_handling), not(test)))] +#[cfg(not(no_global_oom_handling))] #[lang = "exchange_malloc"] #[inline] #[cfg_attr(miri, track_caller)] // even without panics, this helps for Miri backtraces @@ -395,7 +387,7 @@ unsafe extern "Rust" { /// [no_std]: https://doc.rust-lang.org/reference/names/preludes.html#the-no_std-attribute #[stable(feature = "global_alloc", since = "1.28.0")] #[rustc_const_unstable(feature = "const_alloc_error", issue = "92523")] -#[cfg(all(not(no_global_oom_handling), not(test)))] +#[cfg(not(no_global_oom_handling))] #[cold] #[optimize(size)] pub const fn handle_alloc_error(layout: Layout) -> ! { @@ -419,11 +411,7 @@ pub const fn handle_alloc_error(layout: Layout) -> ! { ct_error(layout) } -// For alloc test `std::alloc::handle_alloc_error` can be used directly. -#[cfg(all(not(no_global_oom_handling), test))] -pub use std::alloc::handle_alloc_error; - -#[cfg(all(not(no_global_oom_handling), not(test)))] +#[cfg(not(no_global_oom_handling))] #[doc(hidden)] #[allow(unused_attributes)] #[unstable(feature = "alloc_internals", issue = "none")] diff --git a/library/alloc/src/borrow.rs b/library/alloc/src/borrow.rs index 17dad3277b9..07f51b7614f 100644 --- a/library/alloc/src/borrow.rs +++ b/library/alloc/src/borrow.rs @@ -32,7 +32,7 @@ where /// implementing the `Clone` trait. But `Clone` works only for going from `&T` /// to `T`. The `ToOwned` trait generalizes `Clone` to construct owned data /// from any borrow of a given type. -#[cfg_attr(not(test), rustc_diagnostic_item = "ToOwned")] +#[rustc_diagnostic_item = "ToOwned"] #[stable(feature = "rust1", since = "1.0.0")] pub trait ToOwned { /// The resulting type after obtaining ownership. @@ -54,7 +54,7 @@ pub trait ToOwned { /// ``` #[stable(feature = "rust1", since = "1.0.0")] #[must_use = "cloning is often expensive and is not expected to have side effects"] - #[cfg_attr(not(test), rustc_diagnostic_item = "to_owned_method")] + #[rustc_diagnostic_item = "to_owned_method"] fn to_owned(&self) -> Self::Owned; /// Uses borrowed data to replace owned data, usually by cloning. @@ -175,7 +175,7 @@ where /// } /// ``` #[stable(feature = "rust1", since = "1.0.0")] -#[cfg_attr(not(test), rustc_diagnostic_item = "Cow")] +#[rustc_diagnostic_item = "Cow"] pub enum Cow<'a, B: ?Sized + 'a> where B: ToOwned, diff --git a/library/alloc/src/bstr.rs b/library/alloc/src/bstr.rs index 61e61019b50..338c7ac7f88 100644 --- a/library/alloc/src/bstr.rs +++ b/library/alloc/src/bstr.rs @@ -12,13 +12,10 @@ use core::ops::{ Deref, DerefMut, DerefPure, Index, IndexMut, Range, RangeFrom, RangeFull, RangeInclusive, RangeTo, RangeToInclusive, }; -#[cfg(not(test))] // https://github.com/rust-lang/rust/issues/135100 use core::str::FromStr; use core::{fmt, hash}; -#[cfg(not(test))] // https://github.com/rust-lang/rust/issues/135100 use crate::borrow::{Cow, ToOwned}; -#[cfg(not(test))] // https://github.com/rust-lang/rust/issues/135100 use crate::boxed::Box; #[cfg(not(no_rc))] use crate::rc::Rc; @@ -181,7 +178,6 @@ impl Default for ByteString { // Omitted due to inference failures // -// #[cfg(not(test))] // https://github.com/rust-lang/rust/issues/135100 // #[unstable(feature = "bstr", issue = "134915")] // impl<'a, const N: usize> From<&'a [u8; N]> for ByteString { // #[inline] @@ -190,7 +186,6 @@ impl Default for ByteString { // } // } // -// #[cfg(not(test))] // https://github.com/rust-lang/rust/issues/135100 // #[unstable(feature = "bstr", issue = "134915")] // impl<const N: usize> From<[u8; N]> for ByteString { // #[inline] @@ -199,7 +194,6 @@ impl Default for ByteString { // } // } // -// #[cfg(not(test))] // https://github.com/rust-lang/rust/issues/135100 // #[unstable(feature = "bstr", issue = "134915")] // impl<'a> From<&'a [u8]> for ByteString { // #[inline] @@ -226,7 +220,6 @@ impl From<ByteString> for Vec<u8> { // Omitted due to inference failures // -// #[cfg(not(test))] // https://github.com/rust-lang/rust/issues/135100 // #[unstable(feature = "bstr", issue = "134915")] // impl<'a> From<&'a str> for ByteString { // #[inline] @@ -243,7 +236,6 @@ impl From<ByteString> for Vec<u8> { // } // } -#[cfg(not(test))] // https://github.com/rust-lang/rust/issues/135100 #[unstable(feature = "bstr", issue = "134915")] impl<'a> From<&'a ByteStr> for ByteString { #[inline] @@ -252,7 +244,6 @@ impl<'a> From<&'a ByteStr> for ByteString { } } -#[cfg(not(test))] // https://github.com/rust-lang/rust/issues/135100 #[unstable(feature = "bstr", issue = "134915")] impl<'a> From<ByteString> for Cow<'a, ByteStr> { #[inline] @@ -261,7 +252,6 @@ impl<'a> From<ByteString> for Cow<'a, ByteStr> { } } -#[cfg(not(test))] // https://github.com/rust-lang/rust/issues/135100 #[unstable(feature = "bstr", issue = "134915")] impl<'a> From<&'a ByteString> for Cow<'a, ByteStr> { #[inline] @@ -330,7 +320,6 @@ impl FromIterator<ByteString> for ByteString { } } -#[cfg(not(test))] // https://github.com/rust-lang/rust/issues/135100 #[unstable(feature = "bstr", issue = "134915")] impl FromStr for ByteString { type Err = core::convert::Infallible; @@ -488,7 +477,6 @@ impl PartialEq for ByteString { macro_rules! impl_partial_eq_ord_cow { ($lhs:ty, $rhs:ty) => { - #[cfg(not(test))] // https://github.com/rust-lang/rust/issues/135100 #[allow(unused_lifetimes)] #[unstable(feature = "bstr", issue = "134915")] impl<'a> PartialEq<$rhs> for $lhs { @@ -499,7 +487,6 @@ macro_rules! impl_partial_eq_ord_cow { } } - #[cfg(not(test))] // https://github.com/rust-lang/rust/issues/135100 #[allow(unused_lifetimes)] #[unstable(feature = "bstr", issue = "134915")] impl<'a> PartialEq<$lhs> for $rhs { @@ -510,7 +497,6 @@ macro_rules! impl_partial_eq_ord_cow { } } - #[cfg(not(test))] // https://github.com/rust-lang/rust/issues/135100 #[allow(unused_lifetimes)] #[unstable(feature = "bstr", issue = "134915")] impl<'a> PartialOrd<$rhs> for $lhs { @@ -521,7 +507,6 @@ macro_rules! impl_partial_eq_ord_cow { } } - #[cfg(not(test))] // https://github.com/rust-lang/rust/issues/135100 #[allow(unused_lifetimes)] #[unstable(feature = "bstr", issue = "134915")] impl<'a> PartialOrd<$lhs> for $rhs { @@ -572,7 +557,6 @@ impl PartialOrd for ByteString { } } -#[cfg(not(test))] // https://github.com/rust-lang/rust/issues/135100 #[unstable(feature = "bstr", issue = "134915")] impl ToOwned for ByteStr { type Owned = ByteString; @@ -605,7 +589,6 @@ impl<'a> TryFrom<&'a ByteString> for &'a str { // Additional impls for `ByteStr` that require types from `alloc`: -#[cfg(not(test))] // https://github.com/rust-lang/rust/issues/135100 #[unstable(feature = "bstr", issue = "134915")] impl Clone for Box<ByteStr> { #[inline] @@ -614,7 +597,6 @@ impl Clone for Box<ByteStr> { } } -#[cfg(not(test))] // https://github.com/rust-lang/rust/issues/135100 #[unstable(feature = "bstr", issue = "134915")] impl<'a> From<&'a ByteStr> for Cow<'a, ByteStr> { #[inline] @@ -623,7 +605,6 @@ impl<'a> From<&'a ByteStr> for Cow<'a, ByteStr> { } } -#[cfg(not(test))] // https://github.com/rust-lang/rust/issues/135100 #[unstable(feature = "bstr", issue = "134915")] impl From<Box<[u8]>> for Box<ByteStr> { #[inline] @@ -633,7 +614,6 @@ impl From<Box<[u8]>> for Box<ByteStr> { } } -#[cfg(not(test))] // https://github.com/rust-lang/rust/issues/135100 #[unstable(feature = "bstr", issue = "134915")] impl From<Box<ByteStr>> for Box<[u8]> { #[inline] diff --git a/library/alloc/src/collections/binary_heap/mod.rs b/library/alloc/src/collections/binary_heap/mod.rs index 965fd63a529..b764b8fa5d9 100644 --- a/library/alloc/src/collections/binary_heap/mod.rs +++ b/library/alloc/src/collections/binary_heap/mod.rs @@ -153,7 +153,9 @@ use core::{fmt, ptr}; use crate::alloc::Global; use crate::collections::TryReserveError; use crate::slice; -use crate::vec::{self, AsVecIntoIter, Vec}; +#[cfg(not(test))] +use crate::vec::AsVecIntoIter; +use crate::vec::{self, Vec}; /// A priority queue implemented with a binary heap. /// @@ -1600,6 +1602,7 @@ unsafe impl<I, A: Allocator> InPlaceIterable for IntoIter<I, A> { const MERGE_BY: Option<NonZero<usize>> = NonZero::new(1); } +#[cfg(not(test))] unsafe impl<I> AsVecIntoIter for IntoIter<I> { type Item = I; diff --git a/library/alloc/src/collections/mod.rs b/library/alloc/src/collections/mod.rs index 020cf4d7365..fac4d1a65ab 100644 --- a/library/alloc/src/collections/mod.rs +++ b/library/alloc/src/collections/mod.rs @@ -1,5 +1,8 @@ //! Collection types. +// Note: This module is also included in the alloctests crate using #[path] to +// run the tests. See the comment there for an explanation why this is the case. + #![stable(feature = "rust1", since = "1.0.0")] #[cfg(not(no_global_oom_handling))] @@ -24,41 +27,54 @@ pub mod btree_map { pub mod btree_set { //! An ordered set based on a B-Tree. #[stable(feature = "rust1", since = "1.0.0")] + #[cfg(not(test))] pub use super::btree::set::*; } +#[cfg(not(test))] use core::fmt::Display; #[cfg(not(no_global_oom_handling))] #[stable(feature = "rust1", since = "1.0.0")] #[doc(no_inline)] +#[cfg(not(test))] pub use binary_heap::BinaryHeap; #[cfg(not(no_global_oom_handling))] #[stable(feature = "rust1", since = "1.0.0")] #[doc(no_inline)] +#[cfg(not(test))] pub use btree_map::BTreeMap; #[cfg(not(no_global_oom_handling))] #[stable(feature = "rust1", since = "1.0.0")] #[doc(no_inline)] +#[cfg(not(test))] pub use btree_set::BTreeSet; #[cfg(not(no_global_oom_handling))] #[stable(feature = "rust1", since = "1.0.0")] #[doc(no_inline)] +#[cfg(not(test))] pub use linked_list::LinkedList; #[cfg(not(no_global_oom_handling))] #[stable(feature = "rust1", since = "1.0.0")] #[doc(no_inline)] +#[cfg(not(test))] pub use vec_deque::VecDeque; +#[cfg(not(test))] use crate::alloc::{Layout, LayoutError}; /// The error type for `try_reserve` methods. #[derive(Clone, PartialEq, Eq, Debug)] #[stable(feature = "try_reserve", since = "1.57.0")] +#[cfg(not(test))] pub struct TryReserveError { kind: TryReserveErrorKind, } +#[cfg(test)] +pub use realalloc::collections::TryReserveError; + +#[cfg(not(test))] impl TryReserveError { /// Details about the allocation that caused the error #[inline] @@ -80,6 +96,7 @@ impl TryReserveError { reason = "Uncertain how much info should be exposed", issue = "48043" )] +#[cfg(not(test))] pub enum TryReserveErrorKind { /// Error due to the computed capacity exceeding the collection's maximum /// (usually `isize::MAX` bytes). @@ -103,11 +120,15 @@ pub enum TryReserveErrorKind { }, } +#[cfg(test)] +pub use realalloc::collections::TryReserveErrorKind; + #[unstable( feature = "try_reserve_kind", reason = "Uncertain how much info should be exposed", issue = "48043" )] +#[cfg(not(test))] impl From<TryReserveErrorKind> for TryReserveError { #[inline] fn from(kind: TryReserveErrorKind) -> Self { @@ -116,6 +137,7 @@ impl From<TryReserveErrorKind> for TryReserveError { } #[unstable(feature = "try_reserve_kind", reason = "new API", issue = "48043")] +#[cfg(not(test))] impl From<LayoutError> for TryReserveErrorKind { /// Always evaluates to [`TryReserveErrorKind::CapacityOverflow`]. #[inline] @@ -125,6 +147,7 @@ impl From<LayoutError> for TryReserveErrorKind { } #[stable(feature = "try_reserve", since = "1.57.0")] +#[cfg(not(test))] impl Display for TryReserveError { fn fmt( &self, @@ -152,4 +175,5 @@ trait SpecExtend<I: IntoIterator> { } #[stable(feature = "try_reserve", since = "1.57.0")] +#[cfg(not(test))] impl core::error::Error for TryReserveError {} diff --git a/library/alloc/src/collections/vec_deque/mod.rs b/library/alloc/src/collections/vec_deque/mod.rs index 299c8b8679e..f8844e2d3a5 100644 --- a/library/alloc/src/collections/vec_deque/mod.rs +++ b/library/alloc/src/collections/vec_deque/mod.rs @@ -645,6 +645,7 @@ impl<T, A: Allocator> VecDeque<T, A> { /// initialized rather than only supporting `0..len`. Requires that /// `initialized.start` ≤ `initialized.end` ≤ `capacity`. #[inline] + #[cfg(not(test))] pub(crate) unsafe fn from_contiguous_raw_parts_in( ptr: *mut T, initialized: Range<usize>, diff --git a/library/alloc/src/collections/vec_deque/spec_extend.rs b/library/alloc/src/collections/vec_deque/spec_extend.rs index d246385ca84..7c7072c4c3a 100644 --- a/library/alloc/src/collections/vec_deque/spec_extend.rs +++ b/library/alloc/src/collections/vec_deque/spec_extend.rs @@ -3,6 +3,7 @@ use core::slice; use super::VecDeque; use crate::alloc::Allocator; +#[cfg(not(test))] use crate::vec; // Specialization trait used for VecDeque::extend @@ -78,6 +79,7 @@ where } } +#[cfg(not(test))] impl<T, A: Allocator> SpecExtend<T, vec::IntoIter<T>> for VecDeque<T, A> { #[track_caller] fn spec_extend(&mut self, mut iterator: vec::IntoIter<T>) { diff --git a/library/alloc/src/collections/vec_deque/spec_from_iter.rs b/library/alloc/src/collections/vec_deque/spec_from_iter.rs index 1efe84d6d7d..c80a30c2103 100644 --- a/library/alloc/src/collections/vec_deque/spec_from_iter.rs +++ b/library/alloc/src/collections/vec_deque/spec_from_iter.rs @@ -19,6 +19,7 @@ where } } +#[cfg(not(test))] impl<T> SpecFromIter<T, crate::vec::IntoIter<T>> for VecDeque<T> { #[inline] fn spec_from_iter(iterator: crate::vec::IntoIter<T>) -> Self { diff --git a/library/alloc/src/ffi/c_str.rs b/library/alloc/src/ffi/c_str.rs index fd93045a5ac..f6743c65710 100644 --- a/library/alloc/src/ffi/c_str.rs +++ b/library/alloc/src/ffi/c_str.rs @@ -10,7 +10,6 @@ use core::{fmt, mem, ops, ptr, slice}; use crate::borrow::{Cow, ToOwned}; use crate::boxed::Box; use crate::rc::Rc; -use crate::slice::hack::into_vec; use crate::string::String; #[cfg(target_has_atomic = "ptr")] use crate::sync::Arc; @@ -103,7 +102,7 @@ use crate::vec::Vec; /// of `CString` instances can lead to invalid memory accesses, memory leaks, /// and other memory errors. #[derive(PartialEq, PartialOrd, Eq, Ord, Hash, Clone)] -#[cfg_attr(not(test), rustc_diagnostic_item = "cstring_type")] +#[rustc_diagnostic_item = "cstring_type"] #[stable(feature = "alloc_c_string", since = "1.64.0")] pub struct CString { // Invariant 1: the slice ends with a zero byte and has a length of at least one. @@ -491,7 +490,7 @@ impl CString { #[must_use = "`self` will be dropped if the result is not used"] #[stable(feature = "cstring_into", since = "1.7.0")] pub fn into_bytes(self) -> Vec<u8> { - let mut vec = into_vec(self.into_inner()); + let mut vec = self.into_inner().into_vec(); let _nul = vec.pop(); debug_assert_eq!(_nul, Some(0u8)); vec @@ -512,7 +511,7 @@ impl CString { #[must_use = "`self` will be dropped if the result is not used"] #[stable(feature = "cstring_into", since = "1.7.0")] pub fn into_bytes_with_nul(self) -> Vec<u8> { - into_vec(self.into_inner()) + self.into_inner().into_vec() } /// Returns the contents of this `CString` as a slice of bytes. @@ -573,7 +572,7 @@ impl CString { #[inline] #[must_use] #[stable(feature = "as_c_str", since = "1.20.0")] - #[cfg_attr(not(test), rustc_diagnostic_item = "cstring_as_c_str")] + #[rustc_diagnostic_item = "cstring_as_c_str"] pub fn as_c_str(&self) -> &CStr { &*self } @@ -755,7 +754,6 @@ impl<'a> From<Cow<'a, CStr>> for CString { } } -#[cfg(not(test))] #[stable(feature = "box_from_c_str", since = "1.17.0")] impl From<&CStr> for Box<CStr> { /// Converts a `&CStr` into a `Box<CStr>`, @@ -766,7 +764,6 @@ impl From<&CStr> for Box<CStr> { } } -#[cfg(not(test))] #[stable(feature = "box_from_mut_slice", since = "1.84.0")] impl From<&mut CStr> for Box<CStr> { /// Converts a `&mut CStr` into a `Box<CStr>`, @@ -845,7 +842,6 @@ impl TryFrom<CString> for String { } } -#[cfg(not(test))] #[stable(feature = "more_box_slice_clone", since = "1.29.0")] impl Clone for Box<CStr> { #[inline] @@ -971,7 +967,6 @@ impl Default for Rc<CStr> { } } -#[cfg(not(test))] #[stable(feature = "default_box_extra", since = "1.17.0")] impl Default for Box<CStr> { fn default() -> Box<CStr> { @@ -1080,7 +1075,7 @@ impl ToOwned for CStr { } fn clone_into(&self, target: &mut CString) { - let mut b = into_vec(mem::take(&mut target.inner)); + let mut b = mem::take(&mut target.inner).into_vec(); self.to_bytes_with_nul().clone_into(&mut b); target.inner = b.into_boxed_slice(); } @@ -1113,7 +1108,6 @@ impl AsRef<CStr> for CString { } } -#[cfg(not(test))] impl CStr { /// Converts a `CStr` into a <code>[Cow]<[str]></code>. /// diff --git a/library/alloc/src/lib.rs b/library/alloc/src/lib.rs index 265b68d3b0e..f0cdb1e4e0f 100644 --- a/library/alloc/src/lib.rs +++ b/library/alloc/src/lib.rs @@ -93,7 +93,6 @@ // // Library features: // tidy-alphabetical-start -#![cfg_attr(test, feature(str_as_str))] #![feature(alloc_layout_extra)] #![feature(allocator_api)] #![feature(array_chunks)] @@ -161,13 +160,11 @@ // // Language features: // tidy-alphabetical-start -#![cfg_attr(not(test), feature(coroutine_trait))] -#![cfg_attr(test, feature(panic_update_hook))] -#![cfg_attr(test, feature(test))] #![feature(allocator_internals)] #![feature(allow_internal_unstable)] #![feature(cfg_sanitize)] #![feature(const_precise_live_drops)] +#![feature(coroutine_trait)] #![feature(decl_macro)] #![feature(dropck_eyepatch)] #![feature(fundamental)] @@ -200,15 +197,6 @@ // from other crates, but since this can only appear for lang items, it doesn't seem worth fixing. #![feature(intra_doc_pointers)] -// Allow testing this library -#[cfg(test)] -#[macro_use] -extern crate std; -#[cfg(test)] -extern crate test; -#[cfg(test)] -mod testing; - // Module with internal macros used by other modules (needs to be included before other modules). #[macro_use] mod macros; @@ -216,7 +204,6 @@ mod macros; mod raw_vec; // Heaps provided for low-level allocation strategies - pub mod alloc; // Primitive types using the heaps above @@ -224,13 +211,8 @@ pub mod alloc; // Need to conditionally define the mod from `boxed.rs` to avoid // duplicating the lang-items when building in test cfg; but also need // to allow code to have `use boxed::Box;` declarations. -#[cfg(not(test))] -pub mod boxed; -#[cfg(test)] -mod boxed { - pub(crate) use std::boxed::Box; -} pub mod borrow; +pub mod boxed; #[unstable(feature = "bstr", issue = "134915")] pub mod bstr; pub mod collections; @@ -254,20 +236,3 @@ pub mod __export { pub use core::format_args; pub use core::hint::must_use; } - -#[cfg(test)] -#[allow(dead_code)] // Not used in all configurations -pub(crate) mod test_helpers { - /// Copied from `std::test_helpers::test_rng`, since these tests rely on the - /// seed not being the same for every RNG invocation too. - pub(crate) fn test_rng() -> rand_xorshift::XorShiftRng { - use std::hash::{BuildHasher, Hash, Hasher}; - let mut hasher = std::hash::RandomState::new().build_hasher(); - std::panic::Location::caller().hash(&mut hasher); - let hc64 = hasher.finish(); - let seed_vec = - hc64.to_le_bytes().into_iter().chain(0u8..8).collect::<crate::vec::Vec<u8>>(); - let seed: [u8; 16] = seed_vec.as_slice().try_into().unwrap(); - rand::SeedableRng::from_seed(seed) - } -} diff --git a/library/alloc/src/macros.rs b/library/alloc/src/macros.rs index c000fd6f4ef..214192b8c9a 100644 --- a/library/alloc/src/macros.rs +++ b/library/alloc/src/macros.rs @@ -34,7 +34,7 @@ /// be mindful of side effects. /// /// [`Vec`]: crate::vec::Vec -#[cfg(all(not(no_global_oom_handling), not(test)))] +#[cfg(not(no_global_oom_handling))] #[macro_export] #[stable(feature = "rust1", since = "1.0.0")] #[rustc_diagnostic_item = "vec_macro"] @@ -55,25 +55,6 @@ macro_rules! vec { ); } -// HACK(japaric): with cfg(test) the inherent `[T]::into_vec` method, which is -// required for this macro definition, is not available. Instead use the -// `slice::into_vec` function which is only available with cfg(test) -// NB see the slice::hack module in slice.rs for more information -#[cfg(all(not(no_global_oom_handling), test))] -#[allow(unused_macro_rules)] -macro_rules! vec { - () => ( - $crate::vec::Vec::new() - ); - ($elem:expr; $n:expr) => ( - $crate::vec::from_elem($elem, $n) - ); - ($($x:expr),*) => ( - $crate::slice::into_vec($crate::boxed::Box::new([$($x),*])) - ); - ($($x:expr,)*) => (vec![$($x),*]) -} - /// Creates a `String` using interpolation of runtime expressions. /// /// The first argument `format!` receives is a format string. This must be a string @@ -120,7 +101,7 @@ macro_rules! vec { #[macro_export] #[stable(feature = "rust1", since = "1.0.0")] #[allow_internal_unstable(hint_must_use, liballoc_internals)] -#[cfg_attr(not(test), rustc_diagnostic_item = "format_macro")] +#[rustc_diagnostic_item = "format_macro"] macro_rules! format { ($($arg:tt)*) => { $crate::__export::must_use({ diff --git a/library/alloc/src/raw_vec.rs b/library/alloc/src/raw_vec/mod.rs index 70f32fbaab4..99ebc5c4bfc 100644 --- a/library/alloc/src/raw_vec.rs +++ b/library/alloc/src/raw_vec/mod.rs @@ -1,4 +1,8 @@ #![unstable(feature = "raw_vec_internals", reason = "unstable const warnings", issue = "none")] +#![cfg_attr(test, allow(dead_code))] + +// Note: This module is also included in the alloctests crate using #[path] to +// run the tests. See the comment there for an explanation why this is the case. use core::marker::PhantomData; use core::mem::{ManuallyDrop, MaybeUninit, SizedTypeProperties}; diff --git a/library/alloc/src/rc.rs b/library/alloc/src/rc.rs index 5847bd8f281..fc1cee28d03 100644 --- a/library/alloc/src/rc.rs +++ b/library/alloc/src/rc.rs @@ -263,23 +263,17 @@ use core::ptr::{self, NonNull, drop_in_place}; #[cfg(not(no_global_oom_handling))] use core::slice::from_raw_parts_mut; use core::{borrow, fmt, hint}; -#[cfg(test)] -use std::boxed::Box; #[cfg(not(no_global_oom_handling))] use crate::alloc::handle_alloc_error; use crate::alloc::{AllocError, Allocator, Global, Layout}; use crate::borrow::{Cow, ToOwned}; -#[cfg(not(test))] use crate::boxed::Box; #[cfg(not(no_global_oom_handling))] use crate::string::String; #[cfg(not(no_global_oom_handling))] use crate::vec::Vec; -#[cfg(test)] -mod tests; - // This is repr(C) to future-proof against possible field-reordering, which // would interfere with otherwise safe [into|from]_raw() of transmutable // inner types. @@ -310,7 +304,7 @@ fn rc_inner_layout_for_value_layout(layout: Layout) -> Layout { /// /// [get_mut]: Rc::get_mut #[doc(search_unbox)] -#[cfg_attr(not(test), rustc_diagnostic_item = "Rc")] +#[rustc_diagnostic_item = "Rc"] #[stable(feature = "rust1", since = "1.0.0")] #[rustc_insignificant_dtor] pub struct Rc< @@ -2988,7 +2982,7 @@ impl<T, I: iter::TrustedLen<Item = T>> ToRcSlice<T> for I { /// /// [`upgrade`]: Weak::upgrade #[stable(feature = "rc_weak", since = "1.4.0")] -#[cfg_attr(not(test), rustc_diagnostic_item = "RcWeak")] +#[rustc_diagnostic_item = "RcWeak"] pub struct Weak< T: ?Sized, #[unstable(feature = "allocator_api", issue = "32838")] A: Allocator = Global, diff --git a/library/alloc/src/rc/tests.rs b/library/alloc/src/rc/tests.rs deleted file mode 100644 index 2210a7c24c0..00000000000 --- a/library/alloc/src/rc/tests.rs +++ /dev/null @@ -1,664 +0,0 @@ -use std::cell::RefCell; -use std::clone::Clone; - -use super::*; - -#[test] -fn test_clone() { - let x = Rc::new(RefCell::new(5)); - let y = x.clone(); - *x.borrow_mut() = 20; - assert_eq!(*y.borrow(), 20); -} - -#[test] -fn test_simple() { - let x = Rc::new(5); - assert_eq!(*x, 5); -} - -#[test] -fn test_simple_clone() { - let x = Rc::new(5); - let y = x.clone(); - assert_eq!(*x, 5); - assert_eq!(*y, 5); -} - -#[test] -fn test_destructor() { - let x: Rc<Box<_>> = Rc::new(Box::new(5)); - assert_eq!(**x, 5); -} - -#[test] -fn test_live() { - let x = Rc::new(5); - let y = Rc::downgrade(&x); - assert!(y.upgrade().is_some()); -} - -#[test] -fn test_dead() { - let x = Rc::new(5); - let y = Rc::downgrade(&x); - drop(x); - assert!(y.upgrade().is_none()); -} - -#[test] -fn weak_self_cyclic() { - struct Cycle { - x: RefCell<Option<Weak<Cycle>>>, - } - - let a = Rc::new(Cycle { x: RefCell::new(None) }); - let b = Rc::downgrade(&a.clone()); - *a.x.borrow_mut() = Some(b); - - // hopefully we don't double-free (or leak)... -} - -#[test] -fn is_unique() { - let x = Rc::new(3); - assert!(Rc::is_unique(&x)); - let y = x.clone(); - assert!(!Rc::is_unique(&x)); - drop(y); - assert!(Rc::is_unique(&x)); - let w = Rc::downgrade(&x); - assert!(!Rc::is_unique(&x)); - drop(w); - assert!(Rc::is_unique(&x)); -} - -#[test] -fn test_strong_count() { - let a = Rc::new(0); - assert!(Rc::strong_count(&a) == 1); - let w = Rc::downgrade(&a); - assert!(Rc::strong_count(&a) == 1); - let b = w.upgrade().expect("upgrade of live rc failed"); - assert!(Rc::strong_count(&b) == 2); - assert!(Rc::strong_count(&a) == 2); - drop(w); - drop(a); - assert!(Rc::strong_count(&b) == 1); - let c = b.clone(); - assert!(Rc::strong_count(&b) == 2); - assert!(Rc::strong_count(&c) == 2); -} - -#[test] -fn test_weak_count() { - let a = Rc::new(0); - assert!(Rc::strong_count(&a) == 1); - assert!(Rc::weak_count(&a) == 0); - let w = Rc::downgrade(&a); - assert!(Rc::strong_count(&a) == 1); - assert!(Rc::weak_count(&a) == 1); - drop(w); - assert!(Rc::strong_count(&a) == 1); - assert!(Rc::weak_count(&a) == 0); - let c = a.clone(); - assert!(Rc::strong_count(&a) == 2); - assert!(Rc::weak_count(&a) == 0); - drop(c); -} - -#[test] -fn weak_counts() { - assert_eq!(Weak::weak_count(&Weak::<u64>::new()), 0); - assert_eq!(Weak::strong_count(&Weak::<u64>::new()), 0); - - let a = Rc::new(0); - let w = Rc::downgrade(&a); - assert_eq!(Weak::strong_count(&w), 1); - assert_eq!(Weak::weak_count(&w), 1); - let w2 = w.clone(); - assert_eq!(Weak::strong_count(&w), 1); - assert_eq!(Weak::weak_count(&w), 2); - assert_eq!(Weak::strong_count(&w2), 1); - assert_eq!(Weak::weak_count(&w2), 2); - drop(w); - assert_eq!(Weak::strong_count(&w2), 1); - assert_eq!(Weak::weak_count(&w2), 1); - let a2 = a.clone(); - assert_eq!(Weak::strong_count(&w2), 2); - assert_eq!(Weak::weak_count(&w2), 1); - drop(a2); - drop(a); - assert_eq!(Weak::strong_count(&w2), 0); - assert_eq!(Weak::weak_count(&w2), 0); - drop(w2); -} - -#[test] -fn try_unwrap() { - let x = Rc::new(3); - assert_eq!(Rc::try_unwrap(x), Ok(3)); - let x = Rc::new(4); - let _y = x.clone(); - assert_eq!(Rc::try_unwrap(x), Err(Rc::new(4))); - let x = Rc::new(5); - let _w = Rc::downgrade(&x); - assert_eq!(Rc::try_unwrap(x), Ok(5)); -} - -#[test] -fn into_inner() { - let x = Rc::new(3); - assert_eq!(Rc::into_inner(x), Some(3)); - - let x = Rc::new(4); - let y = Rc::clone(&x); - assert_eq!(Rc::into_inner(x), None); - assert_eq!(Rc::into_inner(y), Some(4)); - - let x = Rc::new(5); - let _w = Rc::downgrade(&x); - assert_eq!(Rc::into_inner(x), Some(5)); -} - -#[test] -fn into_from_raw() { - let x = Rc::new(Box::new("hello")); - let y = x.clone(); - - let x_ptr = Rc::into_raw(x); - drop(y); - unsafe { - assert_eq!(**x_ptr, "hello"); - - let x = Rc::from_raw(x_ptr); - assert_eq!(**x, "hello"); - - assert_eq!(Rc::try_unwrap(x).map(|x| *x), Ok("hello")); - } -} - -#[test] -fn test_into_from_raw_unsized() { - use std::fmt::Display; - use std::string::ToString; - - let rc: Rc<str> = Rc::from("foo"); - - let ptr = Rc::into_raw(rc.clone()); - let rc2 = unsafe { Rc::from_raw(ptr) }; - - assert_eq!(unsafe { &*ptr }, "foo"); - assert_eq!(rc, rc2); - - let rc: Rc<dyn Display> = Rc::new(123); - - let ptr = Rc::into_raw(rc.clone()); - let rc2 = unsafe { Rc::from_raw(ptr) }; - - assert_eq!(unsafe { &*ptr }.to_string(), "123"); - assert_eq!(rc2.to_string(), "123"); -} - -#[test] -fn into_from_weak_raw() { - let x = Rc::new(Box::new("hello")); - let y = Rc::downgrade(&x); - - let y_ptr = Weak::into_raw(y); - unsafe { - assert_eq!(**y_ptr, "hello"); - - let y = Weak::from_raw(y_ptr); - let y_up = Weak::upgrade(&y).unwrap(); - assert_eq!(**y_up, "hello"); - drop(y_up); - - assert_eq!(Rc::try_unwrap(x).map(|x| *x), Ok("hello")); - } -} - -#[test] -fn test_into_from_weak_raw_unsized() { - use std::fmt::Display; - use std::string::ToString; - - let arc: Rc<str> = Rc::from("foo"); - let weak: Weak<str> = Rc::downgrade(&arc); - - let ptr = Weak::into_raw(weak.clone()); - let weak2 = unsafe { Weak::from_raw(ptr) }; - - assert_eq!(unsafe { &*ptr }, "foo"); - assert!(weak.ptr_eq(&weak2)); - - let arc: Rc<dyn Display> = Rc::new(123); - let weak: Weak<dyn Display> = Rc::downgrade(&arc); - - let ptr = Weak::into_raw(weak.clone()); - let weak2 = unsafe { Weak::from_raw(ptr) }; - - assert_eq!(unsafe { &*ptr }.to_string(), "123"); - assert!(weak.ptr_eq(&weak2)); -} - -#[test] -fn get_mut() { - let mut x = Rc::new(3); - *Rc::get_mut(&mut x).unwrap() = 4; - assert_eq!(*x, 4); - let y = x.clone(); - assert!(Rc::get_mut(&mut x).is_none()); - drop(y); - assert!(Rc::get_mut(&mut x).is_some()); - let _w = Rc::downgrade(&x); - assert!(Rc::get_mut(&mut x).is_none()); -} - -#[test] -fn test_cowrc_clone_make_unique() { - let mut cow0 = Rc::new(75); - let mut cow1 = cow0.clone(); - let mut cow2 = cow1.clone(); - - assert!(75 == *Rc::make_mut(&mut cow0)); - assert!(75 == *Rc::make_mut(&mut cow1)); - assert!(75 == *Rc::make_mut(&mut cow2)); - - *Rc::make_mut(&mut cow0) += 1; - *Rc::make_mut(&mut cow1) += 2; - *Rc::make_mut(&mut cow2) += 3; - - assert!(76 == *cow0); - assert!(77 == *cow1); - assert!(78 == *cow2); - - // none should point to the same backing memory - assert!(*cow0 != *cow1); - assert!(*cow0 != *cow2); - assert!(*cow1 != *cow2); -} - -#[test] -fn test_cowrc_clone_unique2() { - let mut cow0 = Rc::new(75); - let cow1 = cow0.clone(); - let cow2 = cow1.clone(); - - assert!(75 == *cow0); - assert!(75 == *cow1); - assert!(75 == *cow2); - - *Rc::make_mut(&mut cow0) += 1; - - assert!(76 == *cow0); - assert!(75 == *cow1); - assert!(75 == *cow2); - - // cow1 and cow2 should share the same contents - // cow0 should have a unique reference - assert!(*cow0 != *cow1); - assert!(*cow0 != *cow2); - assert!(*cow1 == *cow2); -} - -#[test] -fn test_cowrc_clone_weak() { - let mut cow0 = Rc::new(75); - let cow1_weak = Rc::downgrade(&cow0); - - assert!(75 == *cow0); - assert!(75 == *cow1_weak.upgrade().unwrap()); - - *Rc::make_mut(&mut cow0) += 1; - - assert!(76 == *cow0); - assert!(cow1_weak.upgrade().is_none()); -} - -/// This is similar to the doc-test for `Rc::make_mut()`, but on an unsized type (slice). -#[test] -fn test_cowrc_unsized() { - use std::rc::Rc; - - let mut data: Rc<[i32]> = Rc::new([10, 20, 30]); - - Rc::make_mut(&mut data)[0] += 1; // Won't clone anything - let mut other_data = Rc::clone(&data); // Won't clone inner data - Rc::make_mut(&mut data)[1] += 1; // Clones inner data - Rc::make_mut(&mut data)[2] += 1; // Won't clone anything - Rc::make_mut(&mut other_data)[0] *= 10; // Won't clone anything - - // Now `data` and `other_data` point to different allocations. - assert_eq!(*data, [11, 21, 31]); - assert_eq!(*other_data, [110, 20, 30]); -} - -#[test] -fn test_show() { - let foo = Rc::new(75); - assert_eq!(format!("{foo:?}"), "75"); -} - -#[test] -fn test_unsized() { - let foo: Rc<[i32]> = Rc::new([1, 2, 3]); - assert_eq!(foo, foo.clone()); -} - -#[test] -fn test_maybe_thin_unsized() { - // If/when custom thin DSTs exist, this test should be updated to use one - use std::ffi::CStr; - - let x: Rc<CStr> = Rc::from(c"swordfish"); - assert_eq!(format!("{x:?}"), "\"swordfish\""); - let y: Weak<CStr> = Rc::downgrade(&x); - drop(x); - - // At this point, the weak points to a dropped DST - assert!(y.upgrade().is_none()); - // But we still need to be able to get the alloc layout to drop. - // CStr has no drop glue, but custom DSTs might, and need to work. - drop(y); -} - -#[test] -fn test_from_owned() { - let foo = 123; - let foo_rc = Rc::from(foo); - assert!(123 == *foo_rc); -} - -#[test] -fn test_new_weak() { - let foo: Weak<usize> = Weak::new(); - assert!(foo.upgrade().is_none()); -} - -#[test] -fn test_ptr_eq() { - let five = Rc::new(5); - let same_five = five.clone(); - let other_five = Rc::new(5); - - assert!(Rc::ptr_eq(&five, &same_five)); - assert!(!Rc::ptr_eq(&five, &other_five)); -} - -#[test] -fn test_from_str() { - let r: Rc<str> = Rc::from("foo"); - - assert_eq!(&r[..], "foo"); -} - -#[test] -fn test_copy_from_slice() { - let s: &[u32] = &[1, 2, 3]; - let r: Rc<[u32]> = Rc::from(s); - - assert_eq!(&r[..], [1, 2, 3]); -} - -#[test] -fn test_clone_from_slice() { - #[derive(Clone, Debug, Eq, PartialEq)] - struct X(u32); - - let s: &[X] = &[X(1), X(2), X(3)]; - let r: Rc<[X]> = Rc::from(s); - - assert_eq!(&r[..], s); -} - -#[test] -#[should_panic] -fn test_clone_from_slice_panic() { - use std::string::{String, ToString}; - - struct Fail(u32, String); - - impl Clone for Fail { - fn clone(&self) -> Fail { - if self.0 == 2 { - panic!(); - } - Fail(self.0, self.1.clone()) - } - } - - let s: &[Fail] = - &[Fail(0, "foo".to_string()), Fail(1, "bar".to_string()), Fail(2, "baz".to_string())]; - - // Should panic, but not cause memory corruption - let _r: Rc<[Fail]> = Rc::from(s); -} - -#[test] -fn test_from_box() { - let b: Box<u32> = Box::new(123); - let r: Rc<u32> = Rc::from(b); - - assert_eq!(*r, 123); -} - -#[test] -fn test_from_box_str() { - use std::string::String; - - let s = String::from("foo").into_boxed_str(); - assert_eq!((&&&s).as_str(), "foo"); - - let r: Rc<str> = Rc::from(s); - assert_eq!((&r).as_str(), "foo"); - assert_eq!(r.as_str(), "foo"); - - assert_eq!(&r[..], "foo"); -} - -#[test] -fn test_from_box_slice() { - let s = vec![1, 2, 3].into_boxed_slice(); - let r: Rc<[u32]> = Rc::from(s); - - assert_eq!(&r[..], [1, 2, 3]); -} - -#[test] -fn test_from_box_trait() { - use std::fmt::Display; - use std::string::ToString; - - let b: Box<dyn Display> = Box::new(123); - let r: Rc<dyn Display> = Rc::from(b); - - assert_eq!(r.to_string(), "123"); -} - -#[test] -fn test_from_box_trait_zero_sized() { - use std::fmt::Debug; - - let b: Box<dyn Debug> = Box::new(()); - let r: Rc<dyn Debug> = Rc::from(b); - - assert_eq!(format!("{r:?}"), "()"); -} - -#[test] -fn test_from_vec() { - let v = vec![1, 2, 3]; - let r: Rc<[u32]> = Rc::from(v); - - assert_eq!(&r[..], [1, 2, 3]); -} - -#[test] -fn test_downcast() { - use std::any::Any; - - let r1: Rc<dyn Any> = Rc::new(i32::MAX); - let r2: Rc<dyn Any> = Rc::new("abc"); - - assert!(r1.clone().downcast::<u32>().is_err()); - - let r1i32 = r1.downcast::<i32>(); - assert!(r1i32.is_ok()); - assert_eq!(r1i32.unwrap(), Rc::new(i32::MAX)); - - assert!(r2.clone().downcast::<i32>().is_err()); - - let r2str = r2.downcast::<&'static str>(); - assert!(r2str.is_ok()); - assert_eq!(r2str.unwrap(), Rc::new("abc")); -} - -#[test] -fn test_array_from_slice() { - let v = vec![1, 2, 3]; - let r: Rc<[u32]> = Rc::from(v); - - let a: Result<Rc<[u32; 3]>, _> = r.clone().try_into(); - assert!(a.is_ok()); - - let a: Result<Rc<[u32; 2]>, _> = r.clone().try_into(); - assert!(a.is_err()); -} - -#[test] -fn test_rc_cyclic_with_zero_refs() { - struct ZeroRefs { - inner: Weak<ZeroRefs>, - } - - let zero_refs = Rc::new_cyclic(|inner| { - assert_eq!(inner.strong_count(), 0); - assert!(inner.upgrade().is_none()); - ZeroRefs { inner: Weak::new() } - }); - - assert_eq!(Rc::strong_count(&zero_refs), 1); - assert_eq!(Rc::weak_count(&zero_refs), 0); - assert_eq!(zero_refs.inner.strong_count(), 0); - assert_eq!(zero_refs.inner.weak_count(), 0); -} - -#[test] -fn test_rc_cyclic_with_one_ref() { - struct OneRef { - inner: Weak<OneRef>, - } - - let one_ref = Rc::new_cyclic(|inner| { - assert_eq!(inner.strong_count(), 0); - assert!(inner.upgrade().is_none()); - OneRef { inner: inner.clone() } - }); - - assert_eq!(Rc::strong_count(&one_ref), 1); - assert_eq!(Rc::weak_count(&one_ref), 1); - - let one_ref2 = Weak::upgrade(&one_ref.inner).unwrap(); - assert!(Rc::ptr_eq(&one_ref, &one_ref2)); - - assert_eq!(one_ref.inner.strong_count(), 2); - assert_eq!(one_ref.inner.weak_count(), 1); -} - -#[test] -fn test_rc_cyclic_with_two_ref() { - struct TwoRefs { - inner: Weak<TwoRefs>, - inner1: Weak<TwoRefs>, - } - - let two_refs = Rc::new_cyclic(|inner| { - assert_eq!(inner.strong_count(), 0); - assert!(inner.upgrade().is_none()); - TwoRefs { inner: inner.clone(), inner1: inner.clone() } - }); - - assert_eq!(Rc::strong_count(&two_refs), 1); - assert_eq!(Rc::weak_count(&two_refs), 2); - - let two_ref3 = Weak::upgrade(&two_refs.inner).unwrap(); - assert!(Rc::ptr_eq(&two_refs, &two_ref3)); - - let two_ref2 = Weak::upgrade(&two_refs.inner1).unwrap(); - assert!(Rc::ptr_eq(&two_refs, &two_ref2)); - - assert_eq!(Rc::strong_count(&two_refs), 3); - assert_eq!(Rc::weak_count(&two_refs), 2); -} - -#[test] -fn test_unique_rc_weak() { - let rc = UniqueRc::new(42); - let weak = UniqueRc::downgrade(&rc); - assert!(weak.upgrade().is_none()); - - let _rc = UniqueRc::into_rc(rc); - assert_eq!(*weak.upgrade().unwrap(), 42); -} - -#[test] -fn test_unique_rc_drop_weak() { - let rc = UniqueRc::new(42); - let weak = UniqueRc::downgrade(&rc); - mem::drop(weak); - - let rc = UniqueRc::into_rc(rc); - assert_eq!(*rc, 42); -} - -#[test] -fn test_unique_rc_drops_contents() { - let mut dropped = false; - struct DropMe<'a>(&'a mut bool); - impl Drop for DropMe<'_> { - fn drop(&mut self) { - *self.0 = true; - } - } - { - let rc = UniqueRc::new(DropMe(&mut dropped)); - drop(rc); - } - assert!(dropped); -} - -/// Exercise the non-default allocator usage. -#[test] -fn test_unique_rc_with_alloc_drops_contents() { - let mut dropped = false; - struct DropMe<'a>(&'a mut bool); - impl Drop for DropMe<'_> { - fn drop(&mut self) { - *self.0 = true; - } - } - { - let rc = UniqueRc::new_in(DropMe(&mut dropped), std::alloc::System); - drop(rc); - } - assert!(dropped); -} - -#[test] -fn test_unique_rc_weak_clone_holding_ref() { - let mut v = UniqueRc::new(0u8); - let w = UniqueRc::downgrade(&v); - let r = &mut *v; - let _ = w.clone(); // touch weak count - *r = 123; -} - -#[test] -fn test_unique_rc_unsizing_coercion() { - let mut rc: UniqueRc<[u8]> = UniqueRc::new([0u8; 3]); - assert_eq!(rc.len(), 3); - rc[0] = 123; - let rc: Rc<[u8]> = UniqueRc::into_rc(rc); - assert_eq!(*rc, [123, 0, 0]); -} diff --git a/library/alloc/src/slice.rs b/library/alloc/src/slice.rs index 8baf9685062..7c5d22e1ee9 100644 --- a/library/alloc/src/slice.rs +++ b/library/alloc/src/slice.rs @@ -8,9 +8,6 @@ //! A few functions are provided to create a slice from a value reference //! or from a raw pointer. #![stable(feature = "rust1", since = "1.0.0")] -// Many of the usings in this module are only used in the test configuration. -// It's cleaner to just turn off the unused_imports warning than to fix them. -#![cfg_attr(test, allow(unused_imports, dead_code))] use core::borrow::{Borrow, BorrowMut}; #[cfg(not(no_global_oom_handling))] @@ -63,16 +60,6 @@ pub use core::slice::{range, try_range}; //////////////////////////////////////////////////////////////////////////////// // Basic slice extension methods //////////////////////////////////////////////////////////////////////////////// - -// HACK(japaric) needed for the implementation of `vec!` macro during testing -// N.B., see the `hack` module in this file for more details. -#[cfg(test)] -pub use hack::into_vec; -// HACK(japaric) needed for the implementation of `Vec::clone` during testing -// N.B., see the `hack` module in this file for more details. -#[cfg(test)] -pub use hack::to_vec; - use crate::alloc::Allocator; #[cfg(not(no_global_oom_handling))] use crate::alloc::Global; @@ -81,98 +68,6 @@ use crate::borrow::ToOwned; use crate::boxed::Box; use crate::vec::Vec; -// HACK(japaric): With cfg(test) `impl [T]` is not available, these three -// functions are actually methods that are in `impl [T]` but not in -// `core::slice::SliceExt` - we need to supply these functions for the -// `test_permutations` test -#[allow(unreachable_pub)] // cfg(test) pub above -pub(crate) mod hack { - use core::alloc::Allocator; - - use crate::boxed::Box; - use crate::vec::Vec; - - // We shouldn't add inline attribute to this since this is used in - // `vec!` macro mostly and causes perf regression. See #71204 for - // discussion and perf results. - #[allow(missing_docs)] - pub fn into_vec<T, A: Allocator>(b: Box<[T], A>) -> Vec<T, A> { - unsafe { - let len = b.len(); - let (b, alloc) = Box::into_raw_with_allocator(b); - Vec::from_raw_parts_in(b as *mut T, len, len, alloc) - } - } - - #[cfg(not(no_global_oom_handling))] - #[allow(missing_docs)] - #[inline] - pub fn to_vec<T: ConvertVec, A: Allocator>(s: &[T], alloc: A) -> Vec<T, A> { - T::to_vec(s, alloc) - } - - #[cfg(not(no_global_oom_handling))] - pub trait ConvertVec { - fn to_vec<A: Allocator>(s: &[Self], alloc: A) -> Vec<Self, A> - where - Self: Sized; - } - - #[cfg(not(no_global_oom_handling))] - impl<T: Clone> ConvertVec for T { - #[inline] - default fn to_vec<A: Allocator>(s: &[Self], alloc: A) -> Vec<Self, A> { - struct DropGuard<'a, T, A: Allocator> { - vec: &'a mut Vec<T, A>, - num_init: usize, - } - impl<'a, T, A: Allocator> Drop for DropGuard<'a, T, A> { - #[inline] - fn drop(&mut self) { - // SAFETY: - // items were marked initialized in the loop below - unsafe { - self.vec.set_len(self.num_init); - } - } - } - let mut vec = Vec::with_capacity_in(s.len(), alloc); - let mut guard = DropGuard { vec: &mut vec, num_init: 0 }; - let slots = guard.vec.spare_capacity_mut(); - // .take(slots.len()) is necessary for LLVM to remove bounds checks - // and has better codegen than zip. - for (i, b) in s.iter().enumerate().take(slots.len()) { - guard.num_init = i; - slots[i].write(b.clone()); - } - core::mem::forget(guard); - // SAFETY: - // the vec was allocated and initialized above to at least this length. - unsafe { - vec.set_len(s.len()); - } - vec - } - } - - #[cfg(not(no_global_oom_handling))] - impl<T: Copy> ConvertVec for T { - #[inline] - fn to_vec<A: Allocator>(s: &[Self], alloc: A) -> Vec<Self, A> { - let mut v = Vec::with_capacity_in(s.len(), alloc); - // SAFETY: - // allocated above with the capacity of `s`, and initialize to `s.len()` in - // ptr::copy_to_non_overlapping below. - unsafe { - s.as_ptr().copy_to_nonoverlapping(v.as_mut_ptr(), s.len()); - v.set_len(s.len()); - } - v - } - } -} - -#[cfg(not(test))] impl<T> [T] { /// Sorts the slice, preserving initial order of equal elements. /// @@ -501,8 +396,64 @@ impl<T> [T] { where T: Clone, { - // N.B., see the `hack` module in this file for more details. - hack::to_vec(self, alloc) + return T::to_vec(self, alloc); + + trait ConvertVec { + fn to_vec<A: Allocator>(s: &[Self], alloc: A) -> Vec<Self, A> + where + Self: Sized; + } + + impl<T: Clone> ConvertVec for T { + #[inline] + default fn to_vec<A: Allocator>(s: &[Self], alloc: A) -> Vec<Self, A> { + struct DropGuard<'a, T, A: Allocator> { + vec: &'a mut Vec<T, A>, + num_init: usize, + } + impl<'a, T, A: Allocator> Drop for DropGuard<'a, T, A> { + #[inline] + fn drop(&mut self) { + // SAFETY: + // items were marked initialized in the loop below + unsafe { + self.vec.set_len(self.num_init); + } + } + } + let mut vec = Vec::with_capacity_in(s.len(), alloc); + let mut guard = DropGuard { vec: &mut vec, num_init: 0 }; + let slots = guard.vec.spare_capacity_mut(); + // .take(slots.len()) is necessary for LLVM to remove bounds checks + // and has better codegen than zip. + for (i, b) in s.iter().enumerate().take(slots.len()) { + guard.num_init = i; + slots[i].write(b.clone()); + } + core::mem::forget(guard); + // SAFETY: + // the vec was allocated and initialized above to at least this length. + unsafe { + vec.set_len(s.len()); + } + vec + } + } + + impl<T: Copy> ConvertVec for T { + #[inline] + fn to_vec<A: Allocator>(s: &[Self], alloc: A) -> Vec<Self, A> { + let mut v = Vec::with_capacity_in(s.len(), alloc); + // SAFETY: + // allocated above with the capacity of `s`, and initialize to `s.len()` in + // ptr::copy_to_non_overlapping below. + unsafe { + s.as_ptr().copy_to_nonoverlapping(v.as_mut_ptr(), s.len()); + v.set_len(s.len()); + } + v + } + } } /// Converts `self` into a vector without clones or allocation. @@ -522,10 +473,13 @@ impl<T> [T] { #[rustc_allow_incoherent_impl] #[stable(feature = "rust1", since = "1.0.0")] #[inline] - #[cfg_attr(not(test), rustc_diagnostic_item = "slice_into_vec")] + #[rustc_diagnostic_item = "slice_into_vec"] pub fn into_vec<A: Allocator>(self: Box<Self, A>) -> Vec<T, A> { - // N.B., see the `hack` module in this file for more details. - hack::into_vec(self) + unsafe { + let len = self.len(); + let (b, alloc) = Box::into_raw_with_allocator(self); + Vec::from_raw_parts_in(b as *mut T, len, len, alloc) + } } /// Creates a vector by copying a slice `n` times. @@ -666,7 +620,6 @@ impl<T> [T] { } } -#[cfg(not(test))] impl [u8] { /// Returns a vector containing a copy of this slice where each byte /// is mapped to its ASCII upper case equivalent. @@ -883,14 +836,9 @@ impl<T: Copy, A: Allocator> SpecCloneIntoVec<T, A> for [T] { #[stable(feature = "rust1", since = "1.0.0")] impl<T: Clone> ToOwned for [T] { type Owned = Vec<T>; - #[cfg(not(test))] - fn to_owned(&self) -> Vec<T> { - self.to_vec() - } - #[cfg(test)] fn to_owned(&self) -> Vec<T> { - hack::to_vec(self, Global) + self.to_vec() } fn clone_into(&self, target: &mut Vec<T>) { diff --git a/library/alloc/src/str.rs b/library/alloc/src/str.rs index 6fee8d3fe33..0664f2c3cf2 100644 --- a/library/alloc/src/str.rs +++ b/library/alloc/src/str.rs @@ -219,7 +219,6 @@ impl ToOwned for str { } /// Methods for string slices. -#[cfg(not(test))] impl str { /// Converts a `Box<str>` into a `Box<[u8]>` without copying or allocating. /// @@ -631,7 +630,6 @@ pub unsafe fn from_boxed_utf8_unchecked(v: Box<[u8]>) -> Box<str> { #[unstable(feature = "str_internals", issue = "none")] #[doc(hidden)] #[inline] -#[cfg(not(test))] #[cfg(not(no_global_oom_handling))] pub fn convert_while_ascii(s: &str, convert: fn(&u8) -> u8) -> (String, &str) { // Process the input in chunks of 16 bytes to enable auto-vectorization. @@ -704,7 +702,6 @@ pub fn convert_while_ascii(s: &str, convert: fn(&u8) -> u8) -> (String, &str) { } } #[inline] -#[cfg(not(test))] #[cfg(not(no_global_oom_handling))] #[allow(dead_code)] /// Faster implementation of string replacement for ASCII to ASCII cases. diff --git a/library/alloc/src/string.rs b/library/alloc/src/string.rs index 2c034786549..2ba797ab2ad 100644 --- a/library/alloc/src/string.rs +++ b/library/alloc/src/string.rs @@ -356,7 +356,7 @@ use crate::vec::{self, Vec}; /// [`as_str()`]: String::as_str #[derive(PartialEq, PartialOrd, Eq, Ord)] #[stable(feature = "rust1", since = "1.0.0")] -#[cfg_attr(not(test), lang = "String")] +#[lang = "String"] pub struct String { vec: Vec<u8>, } @@ -438,7 +438,7 @@ impl String { /// ``` #[inline] #[rustc_const_stable(feature = "const_string_new", since = "1.39.0")] - #[cfg_attr(not(test), rustc_diagnostic_item = "string_new")] + #[rustc_diagnostic_item = "string_new"] #[stable(feature = "rust1", since = "1.0.0")] #[must_use] pub const fn new() -> String { @@ -501,17 +501,6 @@ impl String { Ok(String { vec: Vec::try_with_capacity(capacity)? }) } - // HACK(japaric): with cfg(test) the inherent `[T]::to_vec` method, which is - // required for this method definition, is not available. Since we don't - // require this method for testing purposes, I'll just stub it - // NB see the slice::hack module in slice.rs for more information - #[inline] - #[cfg(test)] - #[allow(missing_docs)] - pub fn from_str(_: &str) -> String { - panic!("not available with cfg(test)"); - } - /// Converts a vector of bytes to a `String`. /// /// A string ([`String`]) is made of bytes ([`u8`]), and a vector of bytes @@ -570,7 +559,7 @@ impl String { /// [`into_bytes`]: String::into_bytes #[inline] #[stable(feature = "rust1", since = "1.0.0")] - #[cfg_attr(not(test), rustc_diagnostic_item = "string_from_utf8")] + #[rustc_diagnostic_item = "string_from_utf8"] pub fn from_utf8(vec: Vec<u8>) -> Result<String, FromUtf8Error> { match str::from_utf8(&vec) { Ok(..) => Ok(String { vec }), @@ -1071,7 +1060,7 @@ impl String { #[inline] #[must_use] #[stable(feature = "string_as_str", since = "1.7.0")] - #[cfg_attr(not(test), rustc_diagnostic_item = "string_as_str")] + #[rustc_diagnostic_item = "string_as_str"] #[rustc_const_unstable(feature = "const_vec_string_slice", issue = "129041")] pub const fn as_str(&self) -> &str { // SAFETY: String contents are stipulated to be valid UTF-8, invalid contents are an error @@ -1094,7 +1083,7 @@ impl String { #[inline] #[must_use] #[stable(feature = "string_as_str", since = "1.7.0")] - #[cfg_attr(not(test), rustc_diagnostic_item = "string_as_mut_str")] + #[rustc_diagnostic_item = "string_as_mut_str"] #[rustc_const_unstable(feature = "const_vec_string_slice", issue = "129041")] pub const fn as_mut_str(&mut self) -> &mut str { // SAFETY: String contents are stipulated to be valid UTF-8, invalid contents are an error @@ -1117,7 +1106,7 @@ impl String { #[inline] #[stable(feature = "rust1", since = "1.0.0")] #[rustc_confusables("append", "push")] - #[cfg_attr(not(test), rustc_diagnostic_item = "string_push_str")] + #[rustc_diagnostic_item = "string_push_str"] pub fn push_str(&mut self, string: &str) { self.vec.extend_from_slice(string.as_bytes()) } @@ -1755,7 +1744,7 @@ impl String { #[cfg(not(no_global_oom_handling))] #[inline] #[stable(feature = "insert_str", since = "1.16.0")] - #[cfg_attr(not(test), rustc_diagnostic_item = "string_insert_str")] + #[rustc_diagnostic_item = "string_insert_str"] pub fn insert_str(&mut self, idx: usize, string: &str) { assert!(self.is_char_boundary(idx)); @@ -2724,7 +2713,7 @@ impl FromStr for String { /// implementation for free. /// /// [`Display`]: fmt::Display -#[cfg_attr(not(test), rustc_diagnostic_item = "ToString")] +#[rustc_diagnostic_item = "ToString"] #[stable(feature = "rust1", since = "1.0.0")] pub trait ToString { /// Converts the given value to a `String`. @@ -2739,7 +2728,7 @@ pub trait ToString { /// ``` #[rustc_conversion_suggestion] #[stable(feature = "rust1", since = "1.0.0")] - #[cfg_attr(not(test), rustc_diagnostic_item = "to_string_method")] + #[rustc_diagnostic_item = "to_string_method"] fn to_string(&self) -> String; } @@ -2979,7 +2968,6 @@ impl From<&String> for String { } // note: test pulls in std, which causes errors here -#[cfg(not(test))] #[stable(feature = "string_from_box", since = "1.18.0")] impl From<Box<str>> for String { /// Converts the given boxed `str` slice to a [`String`]. diff --git a/library/alloc/src/sync.rs b/library/alloc/src/sync.rs index 21ee59cc538..4999319f618 100644 --- a/library/alloc/src/sync.rs +++ b/library/alloc/src/sync.rs @@ -235,7 +235,7 @@ macro_rules! acquire { /// /// [rc_examples]: crate::rc#examples #[doc(search_unbox)] -#[cfg_attr(not(test), rustc_diagnostic_item = "Arc")] +#[rustc_diagnostic_item = "Arc"] #[stable(feature = "rust1", since = "1.0.0")] #[rustc_insignificant_dtor] pub struct Arc< @@ -312,7 +312,7 @@ impl<T: ?Sized, A: Allocator> Arc<T, A> { /// /// [`upgrade`]: Weak::upgrade #[stable(feature = "arc_weak", since = "1.4.0")] -#[cfg_attr(not(test), rustc_diagnostic_item = "ArcWeak")] +#[rustc_diagnostic_item = "ArcWeak"] pub struct Weak< T: ?Sized, #[unstable(feature = "allocator_api", issue = "32838")] A: Allocator = Global, diff --git a/library/alloc/src/testing/crash_test.rs b/library/alloc/src/testing/crash_test.rs deleted file mode 100644 index 8e00e4f41e5..00000000000 --- a/library/alloc/src/testing/crash_test.rs +++ /dev/null @@ -1,120 +0,0 @@ -use std::cmp::Ordering; -use std::sync::atomic::AtomicUsize; -use std::sync::atomic::Ordering::SeqCst; - -use crate::fmt::Debug; // the `Debug` trait is the only thing we use from `crate::fmt` - -/// A blueprint for crash test dummy instances that monitor particular events. -/// Some instances may be configured to panic at some point. -/// Events are `clone`, `drop` or some anonymous `query`. -/// -/// Crash test dummies are identified and ordered by an id, so they can be used -/// as keys in a BTreeMap. -#[derive(Debug)] -pub(crate) struct CrashTestDummy { - pub id: usize, - cloned: AtomicUsize, - dropped: AtomicUsize, - queried: AtomicUsize, -} - -impl CrashTestDummy { - /// Creates a crash test dummy design. The `id` determines order and equality of instances. - pub(crate) fn new(id: usize) -> CrashTestDummy { - CrashTestDummy { - id, - cloned: AtomicUsize::new(0), - dropped: AtomicUsize::new(0), - queried: AtomicUsize::new(0), - } - } - - /// Creates an instance of a crash test dummy that records what events it experiences - /// and optionally panics. - pub(crate) fn spawn(&self, panic: Panic) -> Instance<'_> { - Instance { origin: self, panic } - } - - /// Returns how many times instances of the dummy have been cloned. - pub(crate) fn cloned(&self) -> usize { - self.cloned.load(SeqCst) - } - - /// Returns how many times instances of the dummy have been dropped. - pub(crate) fn dropped(&self) -> usize { - self.dropped.load(SeqCst) - } - - /// Returns how many times instances of the dummy have had their `query` member invoked. - pub(crate) fn queried(&self) -> usize { - self.queried.load(SeqCst) - } -} - -#[derive(Debug)] -pub(crate) struct Instance<'a> { - origin: &'a CrashTestDummy, - panic: Panic, -} - -#[derive(Copy, Clone, Debug, PartialEq, Eq)] -pub(crate) enum Panic { - Never, - InClone, - InDrop, - InQuery, -} - -impl Instance<'_> { - pub(crate) fn id(&self) -> usize { - self.origin.id - } - - /// Some anonymous query, the result of which is already given. - pub(crate) fn query<R>(&self, result: R) -> R { - self.origin.queried.fetch_add(1, SeqCst); - if self.panic == Panic::InQuery { - panic!("panic in `query`"); - } - result - } -} - -impl Clone for Instance<'_> { - fn clone(&self) -> Self { - self.origin.cloned.fetch_add(1, SeqCst); - if self.panic == Panic::InClone { - panic!("panic in `clone`"); - } - Self { origin: self.origin, panic: Panic::Never } - } -} - -impl Drop for Instance<'_> { - fn drop(&mut self) { - self.origin.dropped.fetch_add(1, SeqCst); - if self.panic == Panic::InDrop { - panic!("panic in `drop`"); - } - } -} - -impl PartialOrd for Instance<'_> { - fn partial_cmp(&self, other: &Self) -> Option<Ordering> { - self.id().partial_cmp(&other.id()) - } -} - -impl Ord for Instance<'_> { - fn cmp(&self, other: &Self) -> Ordering { - self.id().cmp(&other.id()) - } -} - -impl PartialEq for Instance<'_> { - fn eq(&self, other: &Self) -> bool { - self.id().eq(&other.id()) - } -} - -impl Eq for Instance<'_> {} diff --git a/library/alloc/src/testing/mod.rs b/library/alloc/src/testing/mod.rs deleted file mode 100644 index c8457daf93e..00000000000 --- a/library/alloc/src/testing/mod.rs +++ /dev/null @@ -1,3 +0,0 @@ -pub(crate) mod crash_test; -pub(crate) mod ord_chaos; -pub(crate) mod rng; diff --git a/library/alloc/src/testing/ord_chaos.rs b/library/alloc/src/testing/ord_chaos.rs deleted file mode 100644 index 55e1ae5e3de..00000000000 --- a/library/alloc/src/testing/ord_chaos.rs +++ /dev/null @@ -1,81 +0,0 @@ -use std::cell::Cell; -use std::cmp::Ordering::{self, *}; -use std::ptr; - -// Minimal type with an `Ord` implementation violating transitivity. -#[derive(Debug)] -pub(crate) enum Cyclic3 { - A, - B, - C, -} -use Cyclic3::*; - -impl PartialOrd for Cyclic3 { - fn partial_cmp(&self, other: &Self) -> Option<Ordering> { - Some(self.cmp(other)) - } -} - -impl Ord for Cyclic3 { - fn cmp(&self, other: &Self) -> Ordering { - match (self, other) { - (A, A) | (B, B) | (C, C) => Equal, - (A, B) | (B, C) | (C, A) => Less, - (A, C) | (B, A) | (C, B) => Greater, - } - } -} - -impl PartialEq for Cyclic3 { - fn eq(&self, other: &Self) -> bool { - self.cmp(&other) == Equal - } -} - -impl Eq for Cyclic3 {} - -// Controls the ordering of values wrapped by `Governed`. -#[derive(Debug)] -pub(crate) struct Governor { - flipped: Cell<bool>, -} - -impl Governor { - pub(crate) fn new() -> Self { - Governor { flipped: Cell::new(false) } - } - - pub(crate) fn flip(&self) { - self.flipped.set(!self.flipped.get()); - } -} - -// Type with an `Ord` implementation that forms a total order at any moment -// (assuming that `T` respects total order), but can suddenly be made to invert -// that total order. -#[derive(Debug)] -pub(crate) struct Governed<'a, T>(pub T, pub &'a Governor); - -impl<T: Ord> PartialOrd for Governed<'_, T> { - fn partial_cmp(&self, other: &Self) -> Option<Ordering> { - Some(self.cmp(other)) - } -} - -impl<T: Ord> Ord for Governed<'_, T> { - fn cmp(&self, other: &Self) -> Ordering { - assert!(ptr::eq(self.1, other.1)); - let ord = self.0.cmp(&other.0); - if self.1.flipped.get() { ord.reverse() } else { ord } - } -} - -impl<T: PartialEq> PartialEq for Governed<'_, T> { - fn eq(&self, other: &Self) -> bool { - assert!(ptr::eq(self.1, other.1)); - self.0.eq(&other.0) - } -} - -impl<T: Eq> Eq for Governed<'_, T> {} diff --git a/library/alloc/src/testing/rng.rs b/library/alloc/src/testing/rng.rs deleted file mode 100644 index 77d3348f38a..00000000000 --- a/library/alloc/src/testing/rng.rs +++ /dev/null @@ -1,28 +0,0 @@ -/// XorShiftRng -pub(crate) struct DeterministicRng { - count: usize, - x: u32, - y: u32, - z: u32, - w: u32, -} - -impl DeterministicRng { - pub(crate) fn new() -> Self { - DeterministicRng { count: 0, x: 0x193a6754, y: 0xa8a7d469, z: 0x97830e05, w: 0x113ba7bb } - } - - /// Guarantees that each returned number is unique. - pub(crate) fn next(&mut self) -> u32 { - self.count += 1; - assert!(self.count <= 70029); - 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/library/alloc/src/vec/into_iter.rs b/library/alloc/src/vec/into_iter.rs index 52597e41c1c..3eee988b6c9 100644 --- a/library/alloc/src/vec/into_iter.rs +++ b/library/alloc/src/vec/into_iter.rs @@ -472,14 +472,9 @@ where #[cfg(not(no_global_oom_handling))] #[stable(feature = "vec_into_iter_clone", since = "1.8.0")] impl<T: Clone, A: Allocator + Clone> Clone for IntoIter<T, A> { - #[cfg(not(test))] fn clone(&self) -> Self { self.as_slice().to_vec_in(self.alloc.deref().clone()).into_iter() } - #[cfg(test)] - fn clone(&self) -> Self { - crate::slice::to_vec(self.as_slice(), self.alloc.deref().clone()).into_iter() - } } #[stable(feature = "rust1", since = "1.0.0")] diff --git a/library/alloc/src/vec/mod.rs b/library/alloc/src/vec/mod.rs index 49878f2b6fa..ce668540598 100644 --- a/library/alloc/src/vec/mod.rs +++ b/library/alloc/src/vec/mod.rs @@ -404,7 +404,7 @@ mod spec_extend; /// [owned slice]: Box /// [`into_boxed_slice`]: Vec::into_boxed_slice #[stable(feature = "rust1", since = "1.0.0")] -#[cfg_attr(not(test), rustc_diagnostic_item = "Vec")] +#[rustc_diagnostic_item = "Vec"] #[rustc_insignificant_dtor] pub struct Vec<T, #[unstable(feature = "allocator_api", issue = "32838")] A: Allocator = Global> { buf: RawVec<T, A>, @@ -428,7 +428,7 @@ impl<T> Vec<T> { /// ``` #[inline] #[rustc_const_stable(feature = "const_vec_new", since = "1.39.0")] - #[cfg_attr(not(test), rustc_diagnostic_item = "vec_new")] + #[rustc_diagnostic_item = "vec_new"] #[stable(feature = "rust1", since = "1.0.0")] #[must_use] pub const fn new() -> Self { @@ -489,7 +489,7 @@ impl<T> Vec<T> { #[inline] #[stable(feature = "rust1", since = "1.0.0")] #[must_use] - #[cfg_attr(not(test), rustc_diagnostic_item = "vec_with_capacity")] + #[rustc_diagnostic_item = "vec_with_capacity"] #[track_caller] pub fn with_capacity(capacity: usize) -> Self { Self::with_capacity_in(capacity, Global) @@ -1279,7 +1279,7 @@ impl<T, A: Allocator> Vec<T, A> { #[cfg(not(no_global_oom_handling))] #[stable(feature = "rust1", since = "1.0.0")] #[track_caller] - #[cfg_attr(not(test), rustc_diagnostic_item = "vec_reserve")] + #[rustc_diagnostic_item = "vec_reserve"] pub fn reserve(&mut self, additional: usize) { self.buf.reserve(self.len, additional); } @@ -1568,7 +1568,7 @@ impl<T, A: Allocator> Vec<T, A> { /// ``` #[inline] #[stable(feature = "vec_as_slice", since = "1.7.0")] - #[cfg_attr(not(test), rustc_diagnostic_item = "vec_as_slice")] + #[rustc_diagnostic_item = "vec_as_slice"] #[rustc_const_unstable(feature = "const_vec_string_slice", issue = "129041")] pub const fn as_slice(&self) -> &[T] { // SAFETY: `slice::from_raw_parts` requires pointee is a contiguous, aligned buffer of size @@ -1600,7 +1600,7 @@ impl<T, A: Allocator> Vec<T, A> { /// ``` #[inline] #[stable(feature = "vec_as_slice", since = "1.7.0")] - #[cfg_attr(not(test), rustc_diagnostic_item = "vec_as_mut_slice")] + #[rustc_diagnostic_item = "vec_as_mut_slice"] #[rustc_const_unstable(feature = "const_vec_string_slice", issue = "129041")] pub const fn as_mut_slice(&mut self) -> &mut [T] { // SAFETY: `slice::from_raw_parts_mut` requires pointee is a contiguous, aligned buffer of @@ -2511,7 +2511,7 @@ impl<T, A: Allocator> Vec<T, A> { /// Takes *O*(1) time. #[inline] #[stable(feature = "rust1", since = "1.0.0")] - #[cfg_attr(not(test), rustc_diagnostic_item = "vec_pop")] + #[rustc_diagnostic_item = "vec_pop"] pub fn pop(&mut self) -> Option<T> { if self.len == 0 { None @@ -2712,7 +2712,7 @@ impl<T, A: Allocator> Vec<T, A> { /// assert!(!v.is_empty()); /// ``` #[stable(feature = "rust1", since = "1.0.0")] - #[cfg_attr(not(test), rustc_diagnostic_item = "vec_is_empty")] + #[rustc_diagnostic_item = "vec_is_empty"] #[rustc_const_unstable(feature = "const_vec_string_slice", issue = "129041")] pub const fn is_empty(&self) -> bool { self.len() == 0 @@ -3193,7 +3193,7 @@ impl<T: PartialEq, A: Allocator> Vec<T, A> { #[doc(hidden)] #[cfg(not(no_global_oom_handling))] #[stable(feature = "rust1", since = "1.0.0")] -#[cfg_attr(not(test), rustc_diagnostic_item = "vec_from_elem")] +#[rustc_diagnostic_item = "vec_from_elem"] #[track_caller] pub fn from_elem<T: Clone>(elem: T, n: usize) -> Vec<T> { <T as SpecFromElem>::from_elem(elem, n, Global) @@ -3293,23 +3293,12 @@ unsafe impl<T, A: Allocator> ops::DerefPure for Vec<T, A> {} #[cfg(not(no_global_oom_handling))] #[stable(feature = "rust1", since = "1.0.0")] impl<T: Clone, A: Allocator + Clone> Clone for Vec<T, A> { - #[cfg(not(test))] #[track_caller] fn clone(&self) -> Self { let alloc = self.allocator().clone(); <[T]>::to_vec_in(&**self, alloc) } - // HACK(japaric): with cfg(test) the inherent `[T]::to_vec` method, which is - // required for this method definition, is not available. Instead use the - // `slice::to_vec` function which is only available with cfg(test) - // NB see the slice::hack module in slice.rs for more information - #[cfg(test)] - fn clone(&self) -> Self { - let alloc = self.allocator().clone(); - crate::slice::to_vec(&**self, alloc) - } - /// Overwrites the contents of `self` with a clone of the contents of `source`. /// /// This method is preferred over simply assigning `source.clone()` to `self`, @@ -3854,15 +3843,10 @@ impl<T: Clone> From<&[T]> for Vec<T> { /// ``` /// assert_eq!(Vec::from(&[1, 2, 3][..]), vec![1, 2, 3]); /// ``` - #[cfg(not(test))] #[track_caller] fn from(s: &[T]) -> Vec<T> { s.to_vec() } - #[cfg(test)] - fn from(s: &[T]) -> Vec<T> { - crate::slice::to_vec(s, Global) - } } #[cfg(not(no_global_oom_handling))] @@ -3875,15 +3859,10 @@ impl<T: Clone> From<&mut [T]> for Vec<T> { /// ``` /// assert_eq!(Vec::from(&mut [1, 2, 3][..]), vec![1, 2, 3]); /// ``` - #[cfg(not(test))] #[track_caller] fn from(s: &mut [T]) -> Vec<T> { s.to_vec() } - #[cfg(test)] - fn from(s: &mut [T]) -> Vec<T> { - crate::slice::to_vec(s, Global) - } } #[cfg(not(no_global_oom_handling))] @@ -3928,16 +3907,10 @@ impl<T, const N: usize> From<[T; N]> for Vec<T> { /// ``` /// assert_eq!(Vec::from([1, 2, 3]), vec![1, 2, 3]); /// ``` - #[cfg(not(test))] #[track_caller] fn from(s: [T; N]) -> Vec<T> { <[T]>::into_vec(Box::new(s)) } - - #[cfg(test)] - fn from(s: [T; N]) -> Vec<T> { - crate::slice::into_vec(Box::new(s)) - } } #[stable(feature = "vec_from_cow_slice", since = "1.14.0")] @@ -3966,7 +3939,6 @@ where } // note: test pulls in std, which causes errors here -#[cfg(not(test))] #[stable(feature = "vec_from_box", since = "1.18.0")] impl<T, A: Allocator> From<Box<[T], A>> for Vec<T, A> { /// Converts a boxed slice into a vector by transferring ownership of @@ -3985,7 +3957,6 @@ impl<T, A: Allocator> From<Box<[T], A>> for Vec<T, A> { // note: test pulls in std, which causes errors here #[cfg(not(no_global_oom_handling))] -#[cfg(not(test))] #[stable(feature = "box_from_vec", since = "1.20.0")] impl<T, A: Allocator> From<Vec<T, A>> for Box<[T], A> { /// Converts a vector into a boxed slice. diff --git a/library/alloc/tests/alloc.rs b/library/alloc/tests/alloc.rs deleted file mode 100644 index 1e722d66795..00000000000 --- a/library/alloc/tests/alloc.rs +++ /dev/null @@ -1,29 +0,0 @@ -use alloc::alloc::*; -use alloc::boxed::Box; - -extern crate test; -use test::Bencher; - -#[test] -fn allocate_zeroed() { - unsafe { - let layout = Layout::from_size_align(1024, 1).unwrap(); - let ptr = - Global.allocate_zeroed(layout.clone()).unwrap_or_else(|_| handle_alloc_error(layout)); - - let mut i = ptr.as_non_null_ptr().as_ptr(); - let end = i.add(layout.size()); - while i < end { - assert_eq!(*i, 0); - i = i.add(1); - } - Global.deallocate(ptr.as_non_null_ptr(), layout); - } -} - -#[bench] -fn alloc_owned_small(b: &mut Bencher) { - b.iter(|| { - let _: Box<_> = Box::new(10); - }) -} diff --git a/library/alloc/tests/arc.rs b/library/alloc/tests/arc.rs deleted file mode 100644 index 0baa50f439b..00000000000 --- a/library/alloc/tests/arc.rs +++ /dev/null @@ -1,278 +0,0 @@ -use std::any::Any; -use std::cell::{Cell, RefCell}; -use std::iter::TrustedLen; -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, A = std::alloc::Global> = Arc<T, A>; - -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!(size_of::<Box<u16>>() * SHARED_ITER_MAX as usize, 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, 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<[_]>>()); -} - -#[test] -fn weak_may_dangle() { - fn hmm<'a>(val: &'a mut Weak<&'a str>) -> Weak<&'a str> { - val.clone() - } - - // Without #[may_dangle] we get: - let mut val = Weak::new(); - hmm(&mut val); - // ~~~~~~~~ borrowed value does not live long enough - // - // `val` dropped here while still borrowed - // borrow might be used here, when `val` is dropped and runs the `Drop` code for type `std::sync::Weak` -} - -/// Test that a panic from a destructor does not leak the allocation. -#[test] -#[cfg_attr(not(panic = "unwind"), ignore = "test requires unwinding support")] -fn panic_no_leak() { - use std::alloc::{AllocError, Allocator, Global, Layout}; - use std::panic::{AssertUnwindSafe, catch_unwind}; - use std::ptr::NonNull; - - struct AllocCount(Cell<i32>); - unsafe impl Allocator for AllocCount { - fn allocate(&self, layout: Layout) -> Result<NonNull<[u8]>, AllocError> { - self.0.set(self.0.get() + 1); - Global.allocate(layout) - } - unsafe fn deallocate(&self, ptr: NonNull<u8>, layout: Layout) { - self.0.set(self.0.get() - 1); - unsafe { Global.deallocate(ptr, layout) } - } - } - - struct PanicOnDrop; - impl Drop for PanicOnDrop { - fn drop(&mut self) { - panic!("PanicOnDrop"); - } - } - - let alloc = AllocCount(Cell::new(0)); - let rc = Rc::new_in(PanicOnDrop, &alloc); - assert_eq!(alloc.0.get(), 1); - - let panic_message = catch_unwind(AssertUnwindSafe(|| drop(rc))).unwrap_err(); - assert_eq!(*panic_message.downcast_ref::<&'static str>().unwrap(), "PanicOnDrop"); - assert_eq!(alloc.0.get(), 0); -} - -/// This is similar to the doc-test for `Arc::make_mut()`, but on an unsized type (slice). -#[test] -fn make_mut_unsized() { - use alloc::sync::Arc; - - let mut data: Arc<[i32]> = Arc::new([10, 20, 30]); - - Arc::make_mut(&mut data)[0] += 1; // Won't clone anything - let mut other_data = Arc::clone(&data); // Won't clone inner data - Arc::make_mut(&mut data)[1] += 1; // Clones inner data - Arc::make_mut(&mut data)[2] += 1; // Won't clone anything - Arc::make_mut(&mut other_data)[0] *= 10; // Won't clone anything - - // Now `data` and `other_data` point to different allocations. - assert_eq!(*data, [11, 21, 31]); - assert_eq!(*other_data, [110, 20, 30]); -} - -#[allow(unused)] -mod pin_coerce_unsized { - use alloc::sync::Arc; - use core::pin::Pin; - - pub trait MyTrait {} - impl MyTrait for String {} - - // Pin coercion should work for Arc - pub fn pin_arc(arg: Pin<Arc<String>>) -> Pin<Arc<dyn MyTrait>> { - arg - } -} diff --git a/library/alloc/tests/autotraits.rs b/library/alloc/tests/autotraits.rs deleted file mode 100644 index 6b82deeac8a..00000000000 --- a/library/alloc/tests/autotraits.rs +++ /dev/null @@ -1,288 +0,0 @@ -fn require_sync<T: Sync>(_: T) {} -fn require_send_sync<T: Send + Sync>(_: T) {} - -struct NotSend(#[allow(dead_code)] *const ()); -unsafe impl Sync for NotSend {} - -#[test] -fn test_btree_map() { - // Tests of this form are prone to https://github.com/rust-lang/rust/issues/64552. - // - // In theory the async block's future would be Send if the value we hold - // across the await point is Send, and Sync if the value we hold across the - // await point is Sync. - // - // We test autotraits in this convoluted way, instead of a straightforward - // `require_send_sync::<TypeIWantToTest>()`, because the interaction with - // coroutines exposes some current limitations in rustc's ability to prove a - // lifetime bound on the erased coroutine witness types. See the above link. - // - // A typical way this would surface in real code is: - // - // fn spawn<T: Future + Send>(_: T) {} - // - // async fn f() { - // let map = BTreeMap::<u32, Box<dyn Send + Sync>>::new(); - // for _ in &map { - // async {}.await; - // } - // } - // - // fn main() { - // spawn(f()); - // } - // - // where with some unintentionally overconstrained Send impls in alloc's - // internals, the future might incorrectly not be Send even though every - // single type involved in the program is Send and Sync. - require_send_sync(async { - let _v = None::<alloc::collections::btree_map::Iter<'_, &u32, &u32>>; - async {}.await; - }); - - // Testing like this would not catch all issues that the above form catches. - require_send_sync(None::<alloc::collections::btree_map::Iter<'_, &u32, &u32>>); - - require_sync(async { - let _v = None::<alloc::collections::btree_map::Iter<'_, u32, NotSend>>; - async {}.await; - }); - - require_send_sync(async { - let _v = None::<alloc::collections::btree_map::BTreeMap<&u32, &u32>>; - async {}.await; - }); - - require_send_sync(async { - let _v = None::< - alloc::collections::btree_map::ExtractIf<'_, &u32, &u32, fn(&&u32, &mut &u32) -> bool>, - >; - async {}.await; - }); - - require_send_sync(async { - let _v = None::<alloc::collections::btree_map::Entry<'_, &u32, &u32>>; - async {}.await; - }); - - require_send_sync(async { - let _v = None::<alloc::collections::btree_map::IntoIter<&u32, &u32>>; - async {}.await; - }); - - require_send_sync(async { - let _v = None::<alloc::collections::btree_map::IntoKeys<&u32, &u32>>; - async {}.await; - }); - - require_send_sync(async { - let _v = None::<alloc::collections::btree_map::IntoValues<&u32, &u32>>; - async {}.await; - }); - - require_send_sync(async { - let _v = None::<alloc::collections::btree_map::Iter<'_, &u32, &u32>>; - async {}.await; - }); - - require_send_sync(async { - let _v = None::<alloc::collections::btree_map::IterMut<'_, &u32, &u32>>; - async {}.await; - }); - - require_send_sync(async { - let _v = None::<alloc::collections::btree_map::Keys<'_, &u32, &u32>>; - async {}.await; - }); - - require_send_sync(async { - let _v = None::<alloc::collections::btree_map::OccupiedEntry<'_, &u32, &u32>>; - async {}.await; - }); - - require_send_sync(async { - let _v = None::<alloc::collections::btree_map::OccupiedError<'_, &u32, &u32>>; - async {}.await; - }); - - require_send_sync(async { - let _v = None::<alloc::collections::btree_map::Range<'_, &u32, &u32>>; - async {}.await; - }); - - require_send_sync(async { - let _v = None::<alloc::collections::btree_map::RangeMut<'_, &u32, &u32>>; - async {}.await; - }); - - require_send_sync(async { - let _v = None::<alloc::collections::btree_map::VacantEntry<'_, &u32, &u32>>; - async {}.await; - }); - - require_send_sync(async { - let _v = None::<alloc::collections::btree_map::Values<'_, &u32, &u32>>; - async {}.await; - }); - - require_send_sync(async { - let _v = None::<alloc::collections::btree_map::ValuesMut<'_, &u32, &u32>>; - async {}.await; - }); -} - -#[test] -fn test_btree_set() { - require_send_sync(async { - let _v = None::<alloc::collections::btree_set::BTreeSet<&u32>>; - async {}.await; - }); - - require_send_sync(async { - let _v = None::<alloc::collections::btree_set::Difference<'_, &u32>>; - async {}.await; - }); - - require_send_sync(async { - let _v = None::<alloc::collections::btree_set::ExtractIf<'_, &u32, fn(&&u32) -> bool>>; - async {}.await; - }); - - require_send_sync(async { - let _v = None::<alloc::collections::btree_set::Intersection<'_, &u32>>; - async {}.await; - }); - - require_send_sync(async { - let _v = None::<alloc::collections::btree_set::IntoIter<&u32>>; - async {}.await; - }); - - require_send_sync(async { - let _v = None::<alloc::collections::btree_set::Iter<'_, &u32>>; - async {}.await; - }); - - require_send_sync(async { - let _v = None::<alloc::collections::btree_set::Range<'_, &u32>>; - async {}.await; - }); - - require_send_sync(async { - let _v = None::<alloc::collections::btree_set::SymmetricDifference<'_, &u32>>; - async {}.await; - }); - - require_send_sync(async { - let _v = None::<alloc::collections::btree_set::Union<'_, &u32>>; - async {}.await; - }); -} - -#[test] -fn test_binary_heap() { - require_send_sync(async { - let _v = None::<alloc::collections::binary_heap::BinaryHeap<&u32>>; - async {}.await; - }); - - require_send_sync(async { - let _v = None::<alloc::collections::binary_heap::Drain<'_, &u32>>; - async {}.await; - }); - - require_send_sync(async { - let _v = None::<alloc::collections::binary_heap::DrainSorted<'_, &u32>>; - async {}.await; - }); - - require_send_sync(async { - let _v = None::<alloc::collections::binary_heap::IntoIter<&u32>>; - async {}.await; - }); - - require_send_sync(async { - let _v = None::<alloc::collections::binary_heap::IntoIterSorted<&u32>>; - async {}.await; - }); - - require_send_sync(async { - let _v = None::<alloc::collections::binary_heap::Iter<'_, &u32>>; - async {}.await; - }); - - require_send_sync(async { - let _v = None::<alloc::collections::binary_heap::PeekMut<'_, &u32>>; - async {}.await; - }); -} - -#[test] -fn test_linked_list() { - require_send_sync(async { - let _v = None::<alloc::collections::linked_list::Cursor<'_, &u32>>; - async {}.await; - }); - - require_send_sync(async { - let _v = None::<alloc::collections::linked_list::CursorMut<'_, &u32>>; - async {}.await; - }); - - // FIXME - /* - require_send_sync(async { - let _v = - None::<alloc::collections::linked_list::ExtractIf<'_, &u32, fn(&mut &u32) -> bool>>; - async {}.await; - }); - */ - - require_send_sync(async { - let _v = None::<alloc::collections::linked_list::IntoIter<&u32>>; - async {}.await; - }); - - require_send_sync(async { - let _v = None::<alloc::collections::linked_list::Iter<'_, &u32>>; - async {}.await; - }); - - require_send_sync(async { - let _v = None::<alloc::collections::linked_list::IterMut<'_, &u32>>; - async {}.await; - }); - - require_send_sync(async { - let _v = None::<alloc::collections::linked_list::LinkedList<&u32>>; - async {}.await; - }); -} - -#[test] -fn test_vec_deque() { - require_send_sync(async { - let _v = None::<alloc::collections::vec_deque::Drain<'_, &u32>>; - async {}.await; - }); - - require_send_sync(async { - let _v = None::<alloc::collections::vec_deque::IntoIter<&u32>>; - async {}.await; - }); - - require_send_sync(async { - let _v = None::<alloc::collections::vec_deque::Iter<'_, &u32>>; - async {}.await; - }); - - require_send_sync(async { - let _v = None::<alloc::collections::vec_deque::IterMut<'_, &u32>>; - async {}.await; - }); - - require_send_sync(async { - let _v = None::<alloc::collections::vec_deque::VecDeque<&u32>>; - async {}.await; - }); -} diff --git a/library/alloc/tests/borrow.rs b/library/alloc/tests/borrow.rs deleted file mode 100644 index af7efb7d782..00000000000 --- a/library/alloc/tests/borrow.rs +++ /dev/null @@ -1,60 +0,0 @@ -use std::borrow::Cow; -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); -} - -#[test] -fn cow_const() { - // test that the methods of `Cow` are usable in a const context - - const COW: Cow<'_, str> = Cow::Borrowed("moo"); - - const IS_BORROWED: bool = COW.is_borrowed(); - assert!(IS_BORROWED); - - const IS_OWNED: bool = COW.is_owned(); - assert!(!IS_OWNED); -} diff --git a/library/alloc/tests/boxed.rs b/library/alloc/tests/boxed.rs deleted file mode 100644 index 94389cf2de9..00000000000 --- a/library/alloc/tests/boxed.rs +++ /dev/null @@ -1,258 +0,0 @@ -use core::alloc::{AllocError, Allocator, Layout}; -use core::cell::Cell; -use core::mem::MaybeUninit; -use core::ptr::NonNull; - -#[test] -#[expect(dangling_pointers_from_temporaries)] -fn uninitialized_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 reallocates, -/// but the allocator keeps the original pointer. -/// -/// On the other hand, it won't give a false negative: If it fails, then the -/// memory was definitely 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); - } -} - -#[test] -fn box_deref_lval() { - let x = Box::new(Cell::new(5)); - x.set(1000); - assert_eq!(x.get(), 1000); -} - -/// Test that a panic from a destructor does not leak the allocation. -#[test] -#[cfg_attr(not(panic = "unwind"), ignore = "test requires unwinding support")] -fn panic_no_leak() { - use std::alloc::{AllocError, Allocator, Global, Layout}; - use std::panic::{AssertUnwindSafe, catch_unwind}; - use std::ptr::NonNull; - - struct AllocCount(Cell<i32>); - unsafe impl Allocator for AllocCount { - fn allocate(&self, layout: Layout) -> Result<NonNull<[u8]>, AllocError> { - self.0.set(self.0.get() + 1); - Global.allocate(layout) - } - unsafe fn deallocate(&self, ptr: NonNull<u8>, layout: Layout) { - self.0.set(self.0.get() - 1); - unsafe { Global.deallocate(ptr, layout) } - } - } - - struct PanicOnDrop { - _data: u8, - } - impl Drop for PanicOnDrop { - fn drop(&mut self) { - panic!("PanicOnDrop"); - } - } - - let alloc = AllocCount(Cell::new(0)); - let b = Box::new_in(PanicOnDrop { _data: 42 }, &alloc); - assert_eq!(alloc.0.get(), 1); - - let panic_message = catch_unwind(AssertUnwindSafe(|| drop(b))).unwrap_err(); - assert_eq!(*panic_message.downcast_ref::<&'static str>().unwrap(), "PanicOnDrop"); - assert_eq!(alloc.0.get(), 0); -} - -#[allow(unused)] -pub struct ConstAllocator; - -unsafe impl Allocator for ConstAllocator { - fn allocate(&self, layout: Layout) -> Result<NonNull<[u8]>, AllocError> { - match layout.size() { - 0 => Ok(NonNull::slice_from_raw_parts(layout.dangling(), 0)), - _ => unsafe { - let ptr = core::intrinsics::const_allocate(layout.size(), layout.align()); - Ok(NonNull::new_unchecked(ptr as *mut [u8; 0] as *mut [u8])) - }, - } - } - - unsafe fn deallocate(&self, _ptr: NonNull<u8>, layout: Layout) { - match layout.size() { - 0 => { /* do nothing */ } - _ => { /* do nothing too */ } - } - } - - fn allocate_zeroed(&self, layout: Layout) -> Result<NonNull<[u8]>, AllocError> { - let ptr = self.allocate(layout)?; - if layout.size() > 0 { - unsafe { - ptr.as_mut_ptr().write_bytes(0, layout.size()); - } - } - Ok(ptr) - } - - unsafe fn grow( - &self, - ptr: NonNull<u8>, - old_layout: Layout, - new_layout: Layout, - ) -> Result<NonNull<[u8]>, AllocError> { - debug_assert!( - new_layout.size() >= old_layout.size(), - "`new_layout.size()` must be greater than or equal to `old_layout.size()`" - ); - - let new_ptr = self.allocate(new_layout)?; - if new_layout.size() > 0 { - // Safety: `new_ptr` is valid for writes and `ptr` for reads of - // `old_layout.size()`, because `new_layout.size() >= - // old_layout.size()` (which is an invariant that must be upheld by - // callers). - unsafe { - new_ptr.as_mut_ptr().copy_from_nonoverlapping(ptr.as_ptr(), old_layout.size()); - } - // Safety: `ptr` is never used again is also an invariant which must - // be upheld by callers. - unsafe { - self.deallocate(ptr, old_layout); - } - } - Ok(new_ptr) - } - - unsafe fn grow_zeroed( - &self, - ptr: NonNull<u8>, - old_layout: Layout, - new_layout: Layout, - ) -> Result<NonNull<[u8]>, AllocError> { - // Safety: Invariants of `grow_zeroed` and `grow` are the same, and must - // be enforced by callers. - let new_ptr = unsafe { self.grow(ptr, old_layout, new_layout)? }; - if new_layout.size() > 0 { - let old_size = old_layout.size(); - let new_size = new_layout.size(); - let raw_ptr = new_ptr.as_mut_ptr(); - // Safety: - // - `grow` returned Ok, so the returned pointer must be valid for - // `new_size` bytes - // - `new_size` must be larger than `old_size`, which is an - // invariant which must be upheld by callers. - unsafe { - raw_ptr.add(old_size).write_bytes(0, new_size - old_size); - } - } - Ok(new_ptr) - } - - unsafe fn shrink( - &self, - ptr: NonNull<u8>, - old_layout: Layout, - new_layout: Layout, - ) -> Result<NonNull<[u8]>, AllocError> { - debug_assert!( - new_layout.size() <= old_layout.size(), - "`new_layout.size()` must be smaller than or equal to `old_layout.size()`" - ); - - let new_ptr = self.allocate(new_layout)?; - if new_layout.size() > 0 { - // Safety: `new_ptr` and `ptr` are valid for reads/writes of - // `new_layout.size()` because of the invariants of shrink, which - // include `new_layout.size()` being smaller than (or equal to) - // `old_layout.size()`. - unsafe { - new_ptr.as_mut_ptr().copy_from_nonoverlapping(ptr.as_ptr(), new_layout.size()); - } - // Safety: `ptr` is never used again is also an invariant which must - // be upheld by callers. - unsafe { - self.deallocate(ptr, old_layout); - } - } - Ok(new_ptr) - } - - fn by_ref(&self) -> &Self - where - Self: Sized, - { - self - } -} - -#[allow(unused)] -mod pin_coerce_unsized { - use alloc::boxed::Box; - use core::pin::Pin; - - trait MyTrait { - fn action(&self) -> &str; - } - impl MyTrait for String { - fn action(&self) -> &str { - &*self - } - } - struct MyStruct; - impl MyTrait for MyStruct { - fn action(&self) -> &str { - "MyStruct" - } - } - - // Pin coercion should work for Box - fn pin_box<T: MyTrait + 'static>(arg: Pin<Box<T>>) -> Pin<Box<dyn MyTrait>> { - arg - } - - #[test] - fn pin_coerce_unsized_box() { - let my_string = "my string"; - let a_string = Box::pin(String::from(my_string)); - let pin_box_str = pin_box(a_string); - assert_eq!(pin_box_str.as_ref().action(), my_string); - let a_struct = Box::pin(MyStruct); - let pin_box_struct = pin_box(a_struct); - assert_eq!(pin_box_struct.as_ref().action(), "MyStruct"); - } -} diff --git a/library/alloc/tests/btree_set_hash.rs b/library/alloc/tests/btree_set_hash.rs deleted file mode 100644 index 71a3a143209..00000000000 --- a/library/alloc/tests/btree_set_hash.rs +++ /dev/null @@ -1,30 +0,0 @@ -use std::collections::BTreeSet; - -use crate::hash; - -#[test] -fn test_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_prefix_free() { - let x = BTreeSet::from([1, 2, 3]); - let y = BTreeSet::<i32>::new(); - - // If hashed by iteration alone, `(x, y)` and `(y, x)` would visit the same - // order of elements, resulting in the same hash. But now that we also hash - // the length, they get distinct sequences of hashed data. - assert_ne!(hash(&(&x, &y)), hash(&(&y, &x))); -} diff --git a/library/alloc/tests/c_str.rs b/library/alloc/tests/c_str.rs deleted file mode 100644 index 4a581793956..00000000000 --- a/library/alloc/tests/c_str.rs +++ /dev/null @@ -1,19 +0,0 @@ -use std::borrow::Cow::{Borrowed, Owned}; -use std::ffi::CStr; -use std::os::raw::c_char; - -#[test] -fn to_str() { - let data = b"123\xE2\x80\xA6\0"; - let ptr = data.as_ptr() as *const c_char; - unsafe { - assert_eq!(CStr::from_ptr(ptr).to_str(), Ok("123…")); - assert_eq!(CStr::from_ptr(ptr).to_string_lossy(), Borrowed("123…")); - } - let data = b"123\xE2\0"; - let ptr = data.as_ptr() as *const c_char; - unsafe { - assert!(CStr::from_ptr(ptr).to_str().is_err()); - assert_eq!(CStr::from_ptr(ptr).to_string_lossy(), Owned::<str>(format!("123\u{FFFD}"))); - } -} diff --git a/library/alloc/tests/c_str2.rs b/library/alloc/tests/c_str2.rs deleted file mode 100644 index 0f4c27fa123..00000000000 --- a/library/alloc/tests/c_str2.rs +++ /dev/null @@ -1,227 +0,0 @@ -use alloc::ffi::CString; -use alloc::rc::Rc; -use alloc::sync::Arc; -use core::assert_matches::assert_matches; -use core::ffi::{CStr, FromBytesUntilNulError, c_char}; -#[allow(deprecated)] -use core::hash::SipHasher13 as DefaultHasher; -use core::hash::{Hash, Hasher}; - -#[test] -fn c_to_rust() { - let data = b"123\0"; - let ptr = data.as_ptr() as *const c_char; - unsafe { - assert_eq!(CStr::from_ptr(ptr).to_bytes(), b"123"); - assert_eq!(CStr::from_ptr(ptr).to_bytes_with_nul(), b"123\0"); - } -} - -#[test] -fn simple() { - let s = CString::new("1234").unwrap(); - assert_eq!(s.as_bytes(), b"1234"); - assert_eq!(s.as_bytes_with_nul(), b"1234\0"); -} - -#[test] -fn build_with_zero1() { - assert!(CString::new(&b"\0"[..]).is_err()); -} -#[test] -fn build_with_zero2() { - assert!(CString::new(vec![0]).is_err()); -} - -#[test] -fn formatted() { - let s = CString::new(&b"abc\x01\x02\n\xE2\x80\xA6\xFF"[..]).unwrap(); - assert_eq!(format!("{s:?}"), r#""abc\x01\x02\n\xe2\x80\xa6\xff""#); -} - -#[test] -fn borrowed() { - unsafe { - let s = CStr::from_ptr(b"12\0".as_ptr() as *const _); - assert_eq!(s.to_bytes(), b"12"); - assert_eq!(s.to_bytes_with_nul(), b"12\0"); - } -} - -#[test] -fn to_owned() { - let data = b"123\0"; - let ptr = data.as_ptr() as *const c_char; - - let owned = unsafe { CStr::from_ptr(ptr).to_owned() }; - assert_eq!(owned.as_bytes_with_nul(), data); -} - -#[test] -fn equal_hash() { - let data = b"123\xE2\xFA\xA6\0"; - let ptr = data.as_ptr() as *const c_char; - let cstr: &'static CStr = unsafe { CStr::from_ptr(ptr) }; - - #[allow(deprecated)] - let mut s = DefaultHasher::new(); - cstr.hash(&mut s); - let cstr_hash = s.finish(); - #[allow(deprecated)] - let mut s = DefaultHasher::new(); - CString::new(&data[..data.len() - 1]).unwrap().hash(&mut s); - let cstring_hash = s.finish(); - - assert_eq!(cstr_hash, cstring_hash); -} - -#[test] -fn from_bytes_with_nul() { - let data = b"123\0"; - let cstr = CStr::from_bytes_with_nul(data); - assert_eq!(cstr.map(CStr::to_bytes), Ok(&b"123"[..])); - let cstr = CStr::from_bytes_with_nul(data); - assert_eq!(cstr.map(CStr::to_bytes_with_nul), Ok(&b"123\0"[..])); - - unsafe { - let cstr = CStr::from_bytes_with_nul(data); - let cstr_unchecked = CStr::from_bytes_with_nul_unchecked(data); - assert_eq!(cstr, Ok(cstr_unchecked)); - } -} - -#[test] -fn from_bytes_with_nul_unterminated() { - let data = b"123"; - let cstr = CStr::from_bytes_with_nul(data); - assert!(cstr.is_err()); -} - -#[test] -fn from_bytes_with_nul_interior() { - let data = b"1\023\0"; - let cstr = CStr::from_bytes_with_nul(data); - assert!(cstr.is_err()); -} - -#[test] -fn cstr_from_bytes_until_nul() { - // Test an empty slice. This should fail because it - // does not contain a nul byte. - let b = b""; - assert_matches!(CStr::from_bytes_until_nul(&b[..]), Err(FromBytesUntilNulError { .. })); - - // Test a non-empty slice, that does not contain a nul byte. - let b = b"hello"; - assert_matches!(CStr::from_bytes_until_nul(&b[..]), Err(FromBytesUntilNulError { .. })); - - // Test an empty nul-terminated string - let b = b"\0"; - let r = CStr::from_bytes_until_nul(&b[..]).unwrap(); - assert_eq!(r.to_bytes(), b""); - - // Test a slice with the nul byte in the middle - let b = b"hello\0world!"; - let r = CStr::from_bytes_until_nul(&b[..]).unwrap(); - assert_eq!(r.to_bytes(), b"hello"); - - // Test a slice with the nul byte at the end - let b = b"hello\0"; - let r = CStr::from_bytes_until_nul(&b[..]).unwrap(); - assert_eq!(r.to_bytes(), b"hello"); - - // Test a slice with two nul bytes at the end - let b = b"hello\0\0"; - let r = CStr::from_bytes_until_nul(&b[..]).unwrap(); - assert_eq!(r.to_bytes(), b"hello"); - - // Test a slice containing lots of nul bytes - let b = b"\0\0\0\0"; - let r = CStr::from_bytes_until_nul(&b[..]).unwrap(); - assert_eq!(r.to_bytes(), b""); -} - -#[test] -fn into_boxed() { - let orig: &[u8] = b"Hello, world!\0"; - let cstr = CStr::from_bytes_with_nul(orig).unwrap(); - let boxed: Box<CStr> = Box::from(cstr); - let cstring = cstr.to_owned().into_boxed_c_str().into_c_string(); - assert_eq!(cstr, &*boxed); - assert_eq!(&*boxed, &*cstring); - assert_eq!(&*cstring, cstr); -} - -#[test] -fn boxed_default() { - let boxed = <Box<CStr>>::default(); - assert_eq!(boxed.to_bytes_with_nul(), &[0]); -} - -#[test] -fn test_c_str_clone_into() { - let mut c_string = c"lorem".to_owned(); - let c_ptr = c_string.as_ptr(); - let c_str = CStr::from_bytes_with_nul(b"ipsum\0").unwrap(); - c_str.clone_into(&mut c_string); - assert_eq!(c_str, c_string.as_c_str()); - // The exact same size shouldn't have needed to move its allocation - assert_eq!(c_ptr, c_string.as_ptr()); -} - -#[test] -fn into_rc() { - let orig: &[u8] = b"Hello, world!\0"; - let cstr = CStr::from_bytes_with_nul(orig).unwrap(); - let rc: Rc<CStr> = Rc::from(cstr); - let arc: Arc<CStr> = Arc::from(cstr); - - assert_eq!(&*rc, cstr); - assert_eq!(&*arc, cstr); - - let rc2: Rc<CStr> = Rc::from(cstr.to_owned()); - let arc2: Arc<CStr> = Arc::from(cstr.to_owned()); - - assert_eq!(&*rc2, cstr); - assert_eq!(&*arc2, cstr); -} - -#[test] -fn cstr_const_constructor() { - const CSTR: &CStr = unsafe { CStr::from_bytes_with_nul_unchecked(b"Hello, world!\0") }; - - assert_eq!(CSTR.to_str().unwrap(), "Hello, world!"); -} - -#[test] -fn cstr_index_from() { - let original = b"Hello, world!\0"; - let cstr = CStr::from_bytes_with_nul(original).unwrap(); - let result = CStr::from_bytes_with_nul(&original[7..]).unwrap(); - - assert_eq!(&cstr[7..], result); -} - -#[test] -#[should_panic] -fn cstr_index_from_empty() { - let original = b"Hello, world!\0"; - let cstr = CStr::from_bytes_with_nul(original).unwrap(); - let _ = &cstr[original.len()..]; -} - -#[test] -fn c_string_from_empty_string() { - let original = ""; - let cstring = CString::new(original).unwrap(); - assert_eq!(original.as_bytes(), cstring.as_bytes()); - assert_eq!([b'\0'], cstring.as_bytes_with_nul()); -} - -#[test] -fn c_str_from_empty_string() { - let original = b"\0"; - let cstr = CStr::from_bytes_with_nul(original).unwrap(); - assert_eq!([] as [u8; 0], cstr.to_bytes()); - assert_eq!([b'\0'], cstr.to_bytes_with_nul()); -} diff --git a/library/alloc/tests/collections/binary_heap.rs b/library/alloc/tests/collections/binary_heap.rs deleted file mode 100644 index 95f4c3e614f..00000000000 --- a/library/alloc/tests/collections/binary_heap.rs +++ /dev/null @@ -1,580 +0,0 @@ -use alloc::boxed::Box; -use alloc::collections::binary_heap::*; -use std::iter::TrustedLen; -use std::mem; -use std::panic::{AssertUnwindSafe, catch_unwind}; - -use crate::testing::crash_test::{CrashTestDummy, Panic}; - -#[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_leek() { - let data = vec![4, 2, 7]; - let mut heap = BinaryHeap::from(data); - let mut max = heap.peek_mut().unwrap(); - *max = -1; - - // The PeekMut object's Drop impl would have been responsible for moving the - // -1 out of the max position of the BinaryHeap, but we don't run it. - mem::forget(max); - - // Absent some mitigation like leak amplification, the -1 would incorrectly - // end up in the last position of the returned Vec, with the rest of the - // heap's original contents in front of it in sorted order. - let sorted_vec = heap.into_sorted_vec(); - assert!(sorted_vec.is_sorted(), "{:?}", sorted_vec); -} - -#[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::new(2), Box::new(4), Box::new(9)]); - assert_eq!(heap.len(), 3); - assert!(**heap.peek().unwrap() == 9); - heap.push(Box::new(11)); - assert_eq!(heap.len(), 4); - assert!(**heap.peek().unwrap() == 11); - heap.push(Box::new(5)); - assert_eq!(heap.len(), 5); - assert!(**heap.peek().unwrap() == 11); - heap.push(Box::new(27)); - assert_eq!(heap.len(), 6); - assert!(**heap.peek().unwrap() == 27); - heap.push(Box::new(3)); - assert_eq!(heap.len(), 7); - assert!(**heap.peek().unwrap() == 27); - heap.push(Box::new(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_in_place_iterator_specialization() { - let src: Vec<usize> = vec![1, 2, 3]; - let src_ptr = src.as_ptr(); - let heap: BinaryHeap<_> = src.into_iter().map(std::convert::identity).collect(); - let heap_ptr = heap.iter().next().unwrap() as *const usize; - assert_eq!(src_ptr, heap_ptr); - let sink: Vec<_> = heap.into_iter().map(std::convert::identity).collect(); - let sink_ptr = sink.as_ptr(); - assert_eq!(heap_ptr, sink_ptr); -} - -#[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] -#[cfg_attr(not(panic = "unwind"), ignore = "test requires unwinding support")] -fn test_drain_sorted_leak() { - let d0 = CrashTestDummy::new(0); - let d1 = CrashTestDummy::new(1); - let d2 = CrashTestDummy::new(2); - let d3 = CrashTestDummy::new(3); - let d4 = CrashTestDummy::new(4); - let d5 = CrashTestDummy::new(5); - let mut q = BinaryHeap::from(vec![ - d0.spawn(Panic::Never), - d1.spawn(Panic::Never), - d2.spawn(Panic::Never), - d3.spawn(Panic::InDrop), - d4.spawn(Panic::Never), - d5.spawn(Panic::Never), - ]); - - catch_unwind(AssertUnwindSafe(|| drop(q.drain_sorted()))).unwrap_err(); - - assert_eq!(d0.dropped(), 1); - assert_eq!(d1.dropped(), 1); - assert_eq!(d2.dropped(), 1); - assert_eq!(d3.dropped(), 1); - assert_eq!(d4.dropped(), 1); - assert_eq!(d5.dropped(), 1); - assert!(q.is_empty()); -} - -#[test] -fn test_drain_forget() { - let a = CrashTestDummy::new(0); - let b = CrashTestDummy::new(1); - let c = CrashTestDummy::new(2); - let mut q = - BinaryHeap::from(vec![a.spawn(Panic::Never), b.spawn(Panic::Never), c.spawn(Panic::Never)]); - - catch_unwind(AssertUnwindSafe(|| { - let mut it = q.drain(); - it.next(); - mem::forget(it); - })) - .unwrap(); - // Behavior after leaking is explicitly unspecified and order is arbitrary, - // so it's fine if these start failing, but probably worth knowing. - assert!(q.is_empty()); - assert_eq!(a.dropped() + b.dropped() + c.dropped(), 1); - assert_eq!(a.dropped(), 0); - assert_eq!(b.dropped(), 0); - assert_eq!(c.dropped(), 1); - drop(q); - assert_eq!(a.dropped(), 0); - assert_eq!(b.dropped(), 0); - assert_eq!(c.dropped(), 1); -} - -#[test] -fn test_drain_sorted_forget() { - let a = CrashTestDummy::new(0); - let b = CrashTestDummy::new(1); - let c = CrashTestDummy::new(2); - let mut q = - BinaryHeap::from(vec![a.spawn(Panic::Never), b.spawn(Panic::Never), c.spawn(Panic::Never)]); - - catch_unwind(AssertUnwindSafe(|| { - let mut it = q.drain_sorted(); - it.next(); - mem::forget(it); - })) - .unwrap(); - // Behavior after leaking is explicitly unspecified, - // so it's fine if these start failing, but probably worth knowing. - assert_eq!(q.len(), 2); - assert_eq!(a.dropped(), 0); - assert_eq!(b.dropped(), 0); - assert_eq!(c.dropped(), 1); - drop(q); - assert_eq!(a.dropped(), 1); - assert_eq!(b.dropped(), 1); - assert_eq!(c.dropped(), 1); -} - -#[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![100, 10, 50, 1, 2, 20, 30]); - a.retain(|&x| x != 2); - - // Check that 20 moved into 10's place. - assert_eq!(a.clone().into_vec(), [100, 20, 50, 1, 10, 30]); - - a.retain(|_| true); - - assert_eq!(a.clone().into_vec(), [100, 20, 50, 1, 10, 30]); - - a.retain(|&x| x < 50); - - assert_eq!(a.clone().into_vec(), [30, 20, 10, 1]); - - a.retain(|_| false); - - assert!(a.is_empty()); -} - -#[test] -#[cfg_attr(not(panic = "unwind"), ignore = "test requires unwinding support")] -fn test_retain_catch_unwind() { - let mut heap = BinaryHeap::from(vec![3, 1, 2]); - - // Removes the 3, then unwinds out of retain. - let _ = catch_unwind(AssertUnwindSafe(|| { - heap.retain(|e| { - if *e == 1 { - panic!(); - } - false - }); - })); - - // Naively this would be [1, 2] (an invalid heap) if BinaryHeap delegates to - // Vec's retain impl and then does not rebuild the heap after that unwinds. - assert_eq!(heap.into_vec(), [2, 1]); -} - -// old binaryheap failed this test -// -// Integrity means that all elements are present after a comparison panics, -// even if the order might not be correct. -// -// Destructors must be called exactly once per element. -#[test] -#[cfg_attr(not(panic = "unwind"), ignore = "test requires unwinding support")] -fn panic_safe() { - use std::cmp; - use std::panic::{self, AssertUnwindSafe}; - use std::sync::atomic::{AtomicUsize, Ordering}; - - use rand::seq::SliceRandom; - - 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 = crate::test_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/library/alloc/tests/collections/mod.rs b/library/alloc/tests/collections/mod.rs deleted file mode 100644 index e73f3aaef8c..00000000000 --- a/library/alloc/tests/collections/mod.rs +++ /dev/null @@ -1 +0,0 @@ -mod binary_heap; diff --git a/library/alloc/tests/const_fns.rs b/library/alloc/tests/const_fns.rs deleted file mode 100644 index 4e7d7fc833e..00000000000 --- a/library/alloc/tests/const_fns.rs +++ /dev/null @@ -1,38 +0,0 @@ -// Test const functions in the library - -pub const MY_VEC: Vec<usize> = Vec::new(); - -// FIXME(#110395) -// pub const MY_VEC2: Vec<usize> = Default::default(); - -pub const MY_STRING: String = String::new(); - -// pub const MY_STRING2: String = Default::default(); - -// pub const MY_BOXED_SLICE: Box<[usize]> = Default::default(); -// pub const MY_BOXED_STR: Box<str> = Default::default(); - -use std::collections::{BTreeMap, BTreeSet}; - -pub const MY_BTREEMAP: BTreeMap<usize, usize> = BTreeMap::new(); -pub const MAP: &'static BTreeMap<usize, usize> = &MY_BTREEMAP; -pub const MAP_LEN: usize = MAP.len(); -pub const MAP_IS_EMPTY: bool = MAP.is_empty(); - -pub const MY_BTREESET: BTreeSet<usize> = BTreeSet::new(); -pub const SET: &'static BTreeSet<usize> = &MY_BTREESET; -pub const SET_LEN: usize = SET.len(); -pub const SET_IS_EMPTY: bool = SET.is_empty(); - -#[test] -fn test_const() { - assert_eq!(MY_VEC, /* MY_VEC */ vec![]); - assert_eq!(MY_STRING, /* MY_STRING2 */ String::default()); - - // assert_eq!(MY_VEC, *MY_BOXED_SLICE); - // assert_eq!(MY_STRING, *MY_BOXED_STR); - - assert_eq!(MAP_LEN, 0); - assert_eq!(SET_LEN, 0); - assert!(MAP_IS_EMPTY && SET_IS_EMPTY); -} diff --git a/library/alloc/tests/cow_str.rs b/library/alloc/tests/cow_str.rs deleted file mode 100644 index 62a5c245a54..00000000000 --- a/library/alloc/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/library/alloc/tests/fmt.rs b/library/alloc/tests/fmt.rs deleted file mode 100644 index c13074c53b7..00000000000 --- a/library/alloc/tests/fmt.rs +++ /dev/null @@ -1,326 +0,0 @@ -#![deny(warnings)] -// FIXME(static_mut_refs): Do not allow `static_mut_refs` lint -#![allow(static_mut_refs)] - -use std::cell::RefCell; -use std::fmt::{self, Write}; -use std::ptr; - -#[test] -fn test_format() { - let s = fmt::format(format_args!("Hello, {}!", "world")); - assert_eq!(s, "Hello, world!"); -} - -struct A; -struct B; -struct C; -struct D; - -impl fmt::LowerHex for A { - fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - f.write_str("aloha") - } -} -impl fmt::UpperHex for B { - fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - f.write_str("adios") - } -} -impl fmt::Display for C { - fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - f.pad_integral(true, "☃", "123") - } -} -impl fmt::Binary for D { - fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - f.write_str("aa")?; - f.write_char('☃')?; - f.write_str("bb") - } -} - -macro_rules! t { - ($a:expr, $b:expr) => { - assert_eq!($a, $b) - }; -} - -#[test] -fn test_format_macro_interface() { - // Various edge cases without formats - t!(format!(""), ""); - t!(format!("hello"), "hello"); - t!(format!("hello {{"), "hello {"); - - // default formatters should work - t!(format!("{}", 1.0f32), "1"); - t!(format!("{}", 1.0f64), "1"); - t!(format!("{}", "a"), "a"); - t!(format!("{}", "a".to_string()), "a"); - t!(format!("{}", false), "false"); - t!(format!("{}", 'a'), "a"); - - // At least exercise all the formats - t!(format!("{}", true), "true"); - t!(format!("{}", '☃'), "☃"); - t!(format!("{}", 10), "10"); - t!(format!("{}", 10_usize), "10"); - t!(format!("{:?}", '☃'), "'☃'"); - t!(format!("{:?}", 10), "10"); - t!(format!("{:?}", 10_usize), "10"); - t!(format!("{:?}", "true"), "\"true\""); - t!(format!("{:?}", "foo\nbar"), "\"foo\\nbar\""); - t!(format!("{:?}", "foo\n\"bar\"\r\n\'baz\'\t\\qux\\"), r#""foo\n\"bar\"\r\n'baz'\t\\qux\\""#); - t!(format!("{:?}", "foo\0bar\x01baz\u{7f}q\u{75}x"), r#""foo\0bar\u{1}baz\u{7f}qux""#); - t!(format!("{:o}", 10_usize), "12"); - t!(format!("{:x}", 10_usize), "a"); - t!(format!("{:X}", 10_usize), "A"); - t!(format!("{}", "foo"), "foo"); - t!(format!("{}", "foo".to_string()), "foo"); - if cfg!(target_pointer_width = "32") { - t!(format!("{:#p}", ptr::without_provenance::<isize>(0x1234)), "0x00001234"); - t!(format!("{:#p}", ptr::without_provenance_mut::<isize>(0x1234)), "0x00001234"); - } else { - t!(format!("{:#p}", ptr::without_provenance::<isize>(0x1234)), "0x0000000000001234"); - t!(format!("{:#p}", ptr::without_provenance_mut::<isize>(0x1234)), "0x0000000000001234"); - } - t!(format!("{:p}", ptr::without_provenance::<isize>(0x1234)), "0x1234"); - t!(format!("{:p}", ptr::without_provenance_mut::<isize>(0x1234)), "0x1234"); - t!(format!("{A:x}"), "aloha"); - t!(format!("{B:X}"), "adios"); - t!(format!("foo {} ☃☃☃☃☃☃", "bar"), "foo bar ☃☃☃☃☃☃"); - t!(format!("{1} {0}", 0, 1), "1 0"); - t!(format!("{foo} {bar}", foo = 0, bar = 1), "0 1"); - t!(format!("{foo} {1} {bar} {0}", 0, 1, foo = 2, bar = 3), "2 1 3 0"); - t!(format!("{} {0}", "a"), "a a"); - t!(format!("{_foo}", _foo = 6usize), "6"); - t!(format!("{foo_bar}", foo_bar = 1), "1"); - t!(format!("{}", 5 + 5), "10"); - t!(format!("{C:#4}"), "☃123"); - t!(format!("{D:b}"), "aa☃bb"); - - let a: &dyn fmt::Debug = &1; - t!(format!("{a:?}"), "1"); - - // Formatting strings and their arguments - t!(format!("{}", "a"), "a"); - t!(format!("{:4}", "a"), "a "); - t!(format!("{:4}", "☃"), "☃ "); - t!(format!("{:>4}", "a"), " a"); - t!(format!("{:<4}", "a"), "a "); - t!(format!("{:^5}", "a"), " a "); - t!(format!("{:^5}", "aa"), " aa "); - t!(format!("{:^4}", "a"), " a "); - t!(format!("{:^4}", "aa"), " aa "); - t!(format!("{:.4}", "a"), "a"); - t!(format!("{:4.4}", "a"), "a "); - t!(format!("{:4.4}", "aaaaaaaaaaaaaaaaaa"), "aaaa"); - t!(format!("{:<4.4}", "aaaaaaaaaaaaaaaaaa"), "aaaa"); - t!(format!("{:>4.4}", "aaaaaaaaaaaaaaaaaa"), "aaaa"); - t!(format!("{:^4.4}", "aaaaaaaaaaaaaaaaaa"), "aaaa"); - t!(format!("{:>10.4}", "aaaaaaaaaaaaaaaaaa"), " aaaa"); - t!(format!("{:2.4}", "aaaaa"), "aaaa"); - t!(format!("{:2.4}", "aaaa"), "aaaa"); - t!(format!("{:2.4}", "aaa"), "aaa"); - t!(format!("{:2.4}", "aa"), "aa"); - t!(format!("{:2.4}", "a"), "a "); - t!(format!("{:0>2}", "a"), "0a"); - t!(format!("{:.*}", 4, "aaaaaaaaaaaaaaaaaa"), "aaaa"); - t!(format!("{:.1$}", "aaaaaaaaaaaaaaaaaa", 4), "aaaa"); - t!(format!("{:.a$}", "aaaaaaaaaaaaaaaaaa", a = 4), "aaaa"); - t!(format!("{:._a$}", "aaaaaaaaaaaaaaaaaa", _a = 4), "aaaa"); - t!(format!("{:1$}", "a", 4), "a "); - t!(format!("{1:0$}", 4, "a"), "a "); - t!(format!("{:a$}", "a", a = 4), "a "); - t!(format!("{:-#}", "a"), "a"); - t!(format!("{:+#}", "a"), "a"); - t!(format!("{:/^10.8}", "1234567890"), "/12345678/"); - - // Some float stuff - t!(format!("{:}", 1.0f32), "1"); - t!(format!("{:}", 1.0f64), "1"); - t!(format!("{:.3}", 1.0f64), "1.000"); - t!(format!("{:10.3}", 1.0f64), " 1.000"); - t!(format!("{:+10.3}", 1.0f64), " +1.000"); - t!(format!("{:+10.3}", -1.0f64), " -1.000"); - - t!(format!("{:e}", 1.2345e6f32), "1.2345e6"); - t!(format!("{:e}", 1.2345e6f64), "1.2345e6"); - t!(format!("{:E}", 1.2345e6f64), "1.2345E6"); - t!(format!("{:.3e}", 1.2345e6f64), "1.234e6"); - t!(format!("{:10.3e}", 1.2345e6f64), " 1.234e6"); - t!(format!("{:+10.3e}", 1.2345e6f64), " +1.234e6"); - t!(format!("{:+10.3e}", -1.2345e6f64), " -1.234e6"); - - // Float edge cases - t!(format!("{}", -0.0), "-0"); - t!(format!("{:?}", 0.0), "0.0"); - - // sign aware zero padding - t!(format!("{:<3}", 1), "1 "); - t!(format!("{:>3}", 1), " 1"); - t!(format!("{:^3}", 1), " 1 "); - t!(format!("{:03}", 1), "001"); - t!(format!("{:<03}", 1), "001"); - t!(format!("{:>03}", 1), "001"); - t!(format!("{:^03}", 1), "001"); - t!(format!("{:+03}", 1), "+01"); - t!(format!("{:<+03}", 1), "+01"); - t!(format!("{:>+03}", 1), "+01"); - t!(format!("{:^+03}", 1), "+01"); - t!(format!("{:#05x}", 1), "0x001"); - t!(format!("{:<#05x}", 1), "0x001"); - t!(format!("{:>#05x}", 1), "0x001"); - t!(format!("{:^#05x}", 1), "0x001"); - t!(format!("{:05}", 1.2), "001.2"); - t!(format!("{:<05}", 1.2), "001.2"); - t!(format!("{:>05}", 1.2), "001.2"); - t!(format!("{:^05}", 1.2), "001.2"); - t!(format!("{:05}", -1.2), "-01.2"); - t!(format!("{:<05}", -1.2), "-01.2"); - t!(format!("{:>05}", -1.2), "-01.2"); - t!(format!("{:^05}", -1.2), "-01.2"); - t!(format!("{:+05}", 1.2), "+01.2"); - t!(format!("{:<+05}", 1.2), "+01.2"); - t!(format!("{:>+05}", 1.2), "+01.2"); - t!(format!("{:^+05}", 1.2), "+01.2"); - - // Ergonomic format_args! - t!(format!("{0:x} {0:X}", 15), "f F"); - t!(format!("{0:x} {0:X} {}", 15), "f F 15"); - t!(format!("{:x}{0:X}{a:x}{:X}{1:x}{a:X}", 13, 14, a = 15), "dDfEeF"); - t!(format!("{a:x} {a:X}", a = 15), "f F"); - - // And its edge cases - t!( - format!( - "{a:.0$} {b:.0$} {0:.0$}\n{a:.c$} {b:.c$} {c:.c$}", - 4, - a = "abcdefg", - b = "hijklmn", - c = 3 - ), - "abcd hijk 4\nabc hij 3" - ); - t!(format!("{a:.*} {0} {:.*}", 4, 3, "efgh", a = "abcdef"), "abcd 4 efg"); - t!(format!("{:.a$} {a} {a:#x}", "aaaaaa", a = 2), "aa 2 0x2"); - - // Test that pointers don't get truncated. - { - let val = usize::MAX; - let exp = format!("{val:#x}"); - t!(format!("{:p}", std::ptr::without_provenance::<isize>(val)), exp); - } - - // Escaping - t!(format!("{{"), "{"); - t!(format!("}}"), "}"); - - // make sure that format! doesn't move out of local variables - let a = Box::new(3); - let _ = format!("{a}"); - let _ = format!("{a}"); - - // make sure that format! doesn't cause spurious unused-unsafe warnings when - // it's inside of an outer unsafe block - unsafe { - let a: isize = ::std::mem::transmute(3_usize); - let _ = format!("{a}"); - } - - // test that trailing commas are acceptable - let _ = format!("{}", "test",); - let _ = format!("{foo}", foo = "test",); -} - -// Basic test to make sure that we can invoke the `write!` macro with an -// fmt::Write instance. -#[test] -fn test_write() { - let mut buf = String::new(); - let _ = write!(&mut buf, "{}", 3); - { - let w = &mut buf; - let _ = write!(w, "{foo}", foo = 4); - let _ = write!(w, "{}", "hello"); - let _ = writeln!(w, "{}", "line"); - let _ = writeln!(w, "{foo}", foo = "bar"); - let _ = w.write_char('☃'); - let _ = w.write_str("str"); - } - - t!(buf, "34helloline\nbar\n☃str"); -} - -// Just make sure that the macros are defined, there's not really a lot that we -// can do with them just yet (to test the output) -#[test] -fn test_print() { - print!("hi"); - print!("{:?}", vec![0u8]); - println!("hello"); - println!("this is a {}", "test"); - println!("{foo}", foo = "bar"); -} - -// Just make sure that the macros are defined, there's not really a lot that we -// can do with them just yet (to test the output) -#[test] -fn test_format_args() { - let mut buf = String::new(); - { - let w = &mut buf; - let _ = write!(w, "{}", format_args!("{}", 1)); - let _ = write!(w, "{}", format_args!("test")); - let _ = write!(w, "{}", format_args!("{test}", test = 3)); - } - let s = buf; - t!(s, "1test3"); - - let s = fmt::format(format_args!("hello {}", "world")); - t!(s, "hello world"); - let s = format!("{}: {}", "args were", format_args!("hello {}", "world")); - t!(s, "args were: hello world"); -} - -#[test] -fn test_order() { - // Make sure format!() arguments are always evaluated in a left-to-right - // ordering - fn foo() -> isize { - static mut FOO: isize = 0; - unsafe { - FOO += 1; - FOO - } - } - assert_eq!( - format!("{} {} {a} {b} {} {c}", foo(), foo(), foo(), a = foo(), b = foo(), c = foo()), - "1 2 4 5 3 6".to_string() - ); -} - -#[test] -fn test_once() { - // Make sure each argument are evaluated only once even though it may be - // formatted multiple times - fn foo() -> isize { - static mut FOO: isize = 0; - unsafe { - FOO += 1; - FOO - } - } - assert_eq!(format!("{0} {0} {0} {a} {a} {a}", foo(), a = foo()), "1 1 1 2 2 2".to_string()); -} - -#[test] -fn test_refcell() { - let refcell = RefCell::new(5); - assert_eq!(format!("{refcell:?}"), "RefCell { value: 5 }"); - let borrow = refcell.borrow_mut(); - assert_eq!(format!("{refcell:?}"), "RefCell { value: <borrowed> }"); - drop(borrow); - assert_eq!(format!("{refcell:?}"), "RefCell { value: 5 }"); -} diff --git a/library/alloc/tests/heap.rs b/library/alloc/tests/heap.rs deleted file mode 100644 index 246b341eeb3..00000000000 --- a/library/alloc/tests/heap.rs +++ /dev/null @@ -1,44 +0,0 @@ -use std::alloc::{Allocator, 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: Allocator>(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.allocate(Layout::from_size_align(size, align).unwrap()).unwrap() - }) - .collect(); - for &ptr in &pointers { - assert_eq!( - (ptr.as_non_null_ptr().as_ptr() as usize) % align, - 0, - "Got a pointer less aligned than requested" - ) - } - - // Clean up - for &ptr in &pointers { - allocator.deallocate( - ptr.as_non_null_ptr(), - Layout::from_size_align(size, align).unwrap(), - ) - } - } - } - } -} diff --git a/library/alloc/tests/lib.rs b/library/alloc/tests/lib.rs deleted file mode 100644 index 785070fb2bb..00000000000 --- a/library/alloc/tests/lib.rs +++ /dev/null @@ -1,106 +0,0 @@ -#![feature(allocator_api)] -#![feature(alloc_layout_extra)] -#![feature(iter_array_chunks)] -#![feature(assert_matches)] -#![feature(btree_extract_if)] -#![feature(char_max_len)] -#![feature(cow_is_borrowed)] -#![feature(core_intrinsics)] -#![feature(downcast_unchecked)] -#![feature(exact_size_is_empty)] -#![feature(hashmap_internals)] -#![feature(linked_list_cursors)] -#![feature(map_try_insert)] -#![feature(pattern)] -#![feature(trusted_len)] -#![feature(try_reserve_kind)] -#![feature(try_with_capacity)] -#![feature(unboxed_closures)] -#![feature(binary_heap_into_iter_sorted)] -#![feature(binary_heap_drain_sorted)] -#![feature(slice_ptr_get)] -#![feature(inplace_iteration)] -#![feature(iter_advance_by)] -#![feature(iter_next_chunk)] -#![feature(round_char_boundary)] -#![feature(slice_partition_dedup)] -#![feature(string_from_utf8_lossy_owned)] -#![feature(string_remove_matches)] -#![feature(const_btree_len)] -#![feature(const_trait_impl)] -#![feature(panic_update_hook)] -#![feature(pointer_is_aligned_to)] -#![feature(test)] -#![feature(thin_box)] -#![feature(drain_keep_rest)] -#![feature(local_waker)] -#![feature(str_as_str)] -#![feature(strict_provenance_lints)] -#![feature(vec_deque_pop_if)] -#![feature(unique_rc_arc)] -#![feature(macro_metavar_expr_concat)] -#![allow(internal_features)] -#![deny(fuzzy_provenance_casts)] -#![deny(unsafe_op_in_unsafe_fn)] - -extern crate test; - -use std::hash::{DefaultHasher, Hash, Hasher}; - -mod alloc; -mod arc; -mod autotraits; -mod borrow; -mod boxed; -mod btree_set_hash; -mod c_str; -mod c_str2; -mod collections; -mod const_fns; -mod cow_str; -mod fmt; -mod heap; -mod linked_list; -mod misc_tests; -mod rc; -mod slice; -mod sort; -mod str; -mod string; -mod sync; -mod task; -mod testing; -mod thin_box; -mod vec; -mod vec_deque; - -fn hash<T: Hash>(t: &T) -> u64 { - let mut s = DefaultHasher::new(); - t.hash(&mut s); - s.finish() -} - -/// Copied from `std::test_helpers::test_rng`, since these tests rely on the -/// seed not being the same for every RNG invocation too. -fn test_rng() -> rand_xorshift::XorShiftRng { - use std::hash::{BuildHasher, Hash, Hasher}; - let mut hasher = std::hash::RandomState::new().build_hasher(); - std::panic::Location::caller().hash(&mut hasher); - let hc64 = hasher.finish(); - let seed_vec = hc64.to_le_bytes().into_iter().chain(0u8..8).collect::<Vec<u8>>(); - let seed: [u8; 16] = seed_vec.as_slice().try_into().unwrap(); - rand::SeedableRng::from_seed(seed) -} - -#[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/library/alloc/tests/linked_list.rs b/library/alloc/tests/linked_list.rs deleted file mode 100644 index 65b09cb00c4..00000000000 --- a/library/alloc/tests/linked_list.rs +++ /dev/null @@ -1,21 +0,0 @@ -use std::collections::LinkedList; - -#[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)); -} diff --git a/library/alloc/tests/misc_tests.rs b/library/alloc/tests/misc_tests.rs deleted file mode 100644 index b95d11cb07e..00000000000 --- a/library/alloc/tests/misc_tests.rs +++ /dev/null @@ -1,140 +0,0 @@ -//! Test for `boxed` mod. - -use core::any::Any; -use core::ops::Deref; -use std::boxed::Box; - -#[test] -fn test_owned_clone() { - let a = Box::new(5); - let b: Box<i32> = a.clone(); - assert!(a == b); -} - -#[derive(Debug, PartialEq, Eq)] -struct Test; - -#[test] -fn any_move() { - let a = Box::new(8) as Box<dyn Any>; - let b = Box::new(Test) as Box<dyn Any>; - - let a: Box<i32> = a.downcast::<i32>().unwrap(); - assert_eq!(*a, 8); - - let b: Box<Test> = b.downcast::<Test>().unwrap(); - assert_eq!(*b, Test); - - let a = Box::new(8) as Box<dyn Any>; - let b = Box::new(Test) as Box<dyn Any>; - - assert!(a.downcast::<Box<i32>>().is_err()); - assert!(b.downcast::<Box<Test>>().is_err()); -} - -#[test] -fn test_show() { - let a = Box::new(8) as Box<dyn Any>; - let b = Box::new(Test) as Box<dyn Any>; - let a_str = format!("{a:?}"); - let b_str = format!("{b:?}"); - assert_eq!(a_str, "Any { .. }"); - assert_eq!(b_str, "Any { .. }"); - - static EIGHT: usize = 8; - static TEST: Test = Test; - let a = &EIGHT as &dyn Any; - let b = &TEST as &dyn Any; - let s = format!("{a:?}"); - assert_eq!(s, "Any { .. }"); - let s = format!("{b:?}"); - assert_eq!(s, "Any { .. }"); -} - -#[test] -fn deref() { - fn homura<T: Deref<Target = i32>>(_: T) {} - homura(Box::new(765)); -} - -#[test] -fn raw_sized() { - let x = Box::new(17); - let p = Box::into_raw(x); - unsafe { - assert_eq!(17, *p); - *p = 19; - let y = Box::from_raw(p); - assert_eq!(19, *y); - } -} - -#[test] -fn raw_trait() { - trait Foo { - fn get(&self) -> u32; - fn set(&mut self, value: u32); - } - - struct Bar(u32); - - impl Foo for Bar { - fn get(&self) -> u32 { - self.0 - } - - fn set(&mut self, value: u32) { - self.0 = value; - } - } - - let x: Box<dyn Foo> = Box::new(Bar(17)); - let p = Box::into_raw(x); - unsafe { - assert_eq!(17, (*p).get()); - (*p).set(19); - let y: Box<dyn Foo> = Box::from_raw(p); - assert_eq!(19, y.get()); - } -} - -#[test] -fn f64_slice() { - let slice: &[f64] = &[-1.0, 0.0, 1.0, f64::INFINITY]; - let boxed: Box<[f64]> = Box::from(slice); - assert_eq!(&*boxed, slice) -} - -#[test] -fn i64_slice() { - let slice: &[i64] = &[i64::MIN, -2, -1, 0, 1, 2, i64::MAX]; - let boxed: Box<[i64]> = Box::from(slice); - assert_eq!(&*boxed, slice) -} - -#[test] -fn str_slice() { - let s = "Hello, world!"; - let boxed: Box<str> = Box::from(s); - assert_eq!(&*boxed, s) -} - -#[test] -fn boxed_slice_from_iter() { - let iter = 0..100; - let boxed: Box<[u32]> = iter.collect(); - assert_eq!(boxed.len(), 100); - assert_eq!(boxed[7], 7); -} - -#[test] -fn test_array_from_slice() { - let v = vec![1, 2, 3]; - let r: Box<[u32]> = v.into_boxed_slice(); - - let a: Result<Box<[u32; 3]>, _> = r.clone().try_into(); - assert!(a.is_ok()); - - let a: Result<Box<[u32; 2]>, _> = r.clone().try_into(); - assert!(a.is_err()); -} diff --git a/library/alloc/tests/rc.rs b/library/alloc/tests/rc.rs deleted file mode 100644 index 9d82a7621a2..00000000000 --- a/library/alloc/tests/rc.rs +++ /dev/null @@ -1,259 +0,0 @@ -use std::any::Any; -use std::cell::{Cell, RefCell}; -use std::iter::TrustedLen; -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!(size_of::<Box<u16>>() * SHARED_ITER_MAX as usize, 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, 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<[_]>>()); -} - -#[test] -fn weak_may_dangle() { - fn hmm<'a>(val: &'a mut Weak<&'a str>) -> Weak<&'a str> { - val.clone() - } - - // Without #[may_dangle] we get: - let mut val = Weak::new(); - hmm(&mut val); - // ~~~~~~~~ borrowed value does not live long enough - // - // `val` dropped here while still borrowed - // borrow might be used here, when `val` is dropped and runs the `Drop` code for type `std::rc::Weak` -} - -/// Test that a panic from a destructor does not leak the allocation. -#[test] -#[cfg_attr(not(panic = "unwind"), ignore = "test requires unwinding support")] -fn panic_no_leak() { - use std::alloc::{AllocError, Allocator, Global, Layout}; - use std::panic::{AssertUnwindSafe, catch_unwind}; - use std::ptr::NonNull; - - struct AllocCount(Cell<i32>); - unsafe impl Allocator for AllocCount { - fn allocate(&self, layout: Layout) -> Result<NonNull<[u8]>, AllocError> { - self.0.set(self.0.get() + 1); - Global.allocate(layout) - } - unsafe fn deallocate(&self, ptr: NonNull<u8>, layout: Layout) { - self.0.set(self.0.get() - 1); - unsafe { Global.deallocate(ptr, layout) } - } - } - - struct PanicOnDrop; - impl Drop for PanicOnDrop { - fn drop(&mut self) { - panic!("PanicOnDrop"); - } - } - - let alloc = AllocCount(Cell::new(0)); - let rc = Rc::new_in(PanicOnDrop, &alloc); - assert_eq!(alloc.0.get(), 1); - - let panic_message = catch_unwind(AssertUnwindSafe(|| drop(rc))).unwrap_err(); - assert_eq!(*panic_message.downcast_ref::<&'static str>().unwrap(), "PanicOnDrop"); - assert_eq!(alloc.0.get(), 0); -} - -#[allow(unused)] -mod pin_coerce_unsized { - use alloc::rc::{Rc, UniqueRc}; - use core::pin::Pin; - - pub trait MyTrait {} - impl MyTrait for String {} - - // Pin coercion should work for Rc - pub fn pin_rc(arg: Pin<Rc<String>>) -> Pin<Rc<dyn MyTrait>> { - arg - } - pub fn pin_unique_rc(arg: Pin<UniqueRc<String>>) -> Pin<UniqueRc<dyn MyTrait>> { - arg - } -} diff --git a/library/alloc/tests/slice.rs b/library/alloc/tests/slice.rs deleted file mode 100644 index 2516563187f..00000000000 --- a/library/alloc/tests/slice.rs +++ /dev/null @@ -1,1668 +0,0 @@ -use std::cmp::Ordering::{Equal, Greater, Less}; -use std::convert::identity; -use std::rc::Rc; -use std::{fmt, panic}; - -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!(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::new(0)); - v.push(Box::new(0)); - v.push(Box::new(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::new(6), Box::new(5), Box::new(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::new(6), Box::new(5), Box::new(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] -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_split_iterator() { - 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_split_iterator_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_split_iterator_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_split_iterator_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_split_iterator_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_splitn_iterator() { - 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_splitn_iterator_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_rsplit_iterator() { - 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_rsplitn_iterator() { - 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_split_iterators_size_hint() { - #[derive(Copy, Clone)] - enum Bounds { - Lower, - Upper, - } - fn assert_tight_size_hints(mut it: impl Iterator, which: Bounds, ctx: impl fmt::Display) { - match which { - Bounds::Lower => { - let mut lower_bounds = vec![it.size_hint().0]; - while let Some(_) = it.next() { - lower_bounds.push(it.size_hint().0); - } - let target: Vec<_> = (0..lower_bounds.len()).rev().collect(); - assert_eq!(lower_bounds, target, "lower bounds incorrect or not tight: {}", ctx); - } - Bounds::Upper => { - let mut upper_bounds = vec![it.size_hint().1]; - while let Some(_) = it.next() { - upper_bounds.push(it.size_hint().1); - } - let target: Vec<_> = (0..upper_bounds.len()).map(Some).rev().collect(); - assert_eq!(upper_bounds, target, "upper bounds incorrect or not tight: {}", ctx); - } - } - } - - for len in 0..=2 { - let mut v: Vec<u8> = (0..len).collect(); - - // p: predicate, b: bound selection - for (p, b) in [ - // with a predicate always returning false, the split*-iterators - // become maximally short, so the size_hint lower bounds are tight - ((|_| false) as fn(&_) -> _, Bounds::Lower), - // with a predicate always returning true, the split*-iterators - // become maximally long, so the size_hint upper bounds are tight - ((|_| true) as fn(&_) -> _, Bounds::Upper), - ] { - use {assert_tight_size_hints as a, format_args as f}; - - a(v.split(p), b, "split"); - a(v.split_mut(p), b, "split_mut"); - a(v.split_inclusive(p), b, "split_inclusive"); - a(v.split_inclusive_mut(p), b, "split_inclusive_mut"); - a(v.rsplit(p), b, "rsplit"); - a(v.rsplit_mut(p), b, "rsplit_mut"); - - for n in 0..=3 { - a(v.splitn(n, p), b, f!("splitn, n = {n}")); - a(v.splitn_mut(n, p), b, f!("splitn_mut, n = {n}")); - a(v.rsplitn(n, p), b, f!("rsplitn, n = {n}")); - a(v.rsplitn_mut(n, p), b, f!("rsplitn_mut, n = {n}")); - } - } - } -} - -#[test] -fn test_windows_iterator() { - 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_windows_iterator_0() { - let v = &[1, 2, 3, 4]; - let _it = v.windows(0); -} - -#[test] -fn test_chunks_iterator() { - 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_chunks_iterator_0() { - let v = &[1, 2, 3, 4]; - let _it = v.chunks(0); -} - -#[test] -fn test_chunks_exact_iterator() { - 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_exact_iterator_0() { - let v = &[1, 2, 3, 4]; - let _it = v.chunks_exact(0); -} - -#[test] -fn test_rchunks_iterator() { - 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_rchunks_iterator_0() { - let v = &[1, 2, 3, 4]; - let _it = v.rchunks(0); -} - -#[test] -fn test_rchunks_exact_iterator() { - 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_exact_iterator_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_split_iterator() { - 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_split_iterator_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::new([1, 2, 3]); - let ys = xs.to_vec(); - assert_eq!(ys, [1, 2, 3]); -} - -#[test] -fn test_in_place_iterator_specialization() { - let src: Box<[usize]> = Box::new([1, 2, 3]); - let src_ptr = src.as_ptr(); - let sink: Box<_> = src.into_vec().into_iter().map(std::convert::identity).collect(); - let sink_ptr = sink.as_ptr(); - assert_eq!(src_ptr, sink_ptr); -} - -#[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(not(panic = "unwind"), ignore = "test requires unwinding support")] -fn test_box_slice_clone_panics() { - use std::sync::Arc; - use std::sync::atomic::{AtomicUsize, Ordering}; - - 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 = "source slice length (4) does not match destination slice length (5)")] -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 = "source slice length (4) does not match destination slice length (3)")] -fn test_copy_from_slice_dst_shorter() { - let src = [0, 1, 2, 3]; - let mut dst = [0; 3]; - dst.copy_from_slice(&src); -} - -#[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]); -} - -#[test] -#[allow(unreachable_patterns)] -fn subslice_patterns() { - // This test comprehensively checks the passing static and dynamic semantics - // of subslice patterns `..`, `x @ ..`, `ref x @ ..`, and `ref mut @ ..` - // in slice patterns `[$($pat), $(,)?]` . - - #[derive(PartialEq, Debug, Clone)] - struct N(u8); - - macro_rules! n { - ($($e:expr),* $(,)?) => { - [$(N($e)),*] - } - } - - macro_rules! c { - ($inp:expr, $typ:ty, $out:expr $(,)?) => { - assert_eq!($out, identity::<$typ>($inp)) - }; - } - - macro_rules! m { - ($e:expr, $p:pat => $b:expr) => { - match $e { - $p => $b, - _ => panic!(), - } - }; - } - - // == Slices == - - // Matching slices using `ref` patterns: - let mut v = vec![N(0), N(1), N(2), N(3), N(4)]; - let mut vc = (0..=4).collect::<Vec<u8>>(); - - let [..] = v[..]; // Always matches. - m!(v[..], [N(0), ref sub @ .., N(4)] => c!(sub, &[N], n![1, 2, 3])); - m!(v[..], [N(0), ref sub @ ..] => c!(sub, &[N], n![1, 2, 3, 4])); - m!(v[..], [ref sub @ .., N(4)] => c!(sub, &[N], n![0, 1, 2, 3])); - m!(v[..], [ref sub @ .., _, _, _, _, _] => c!(sub, &[N], &n![] as &[N])); - m!(v[..], [_, _, _, _, _, ref sub @ ..] => c!(sub, &[N], &n![] as &[N])); - m!(vc[..], [x, .., y] => c!((x, y), (u8, u8), (0, 4))); - - // Matching slices using `ref mut` patterns: - let [..] = v[..]; // Always matches. - m!(v[..], [N(0), ref mut sub @ .., N(4)] => c!(sub, &mut [N], n![1, 2, 3])); - m!(v[..], [N(0), ref mut sub @ ..] => c!(sub, &mut [N], n![1, 2, 3, 4])); - m!(v[..], [ref mut sub @ .., N(4)] => c!(sub, &mut [N], n![0, 1, 2, 3])); - m!(v[..], [ref mut sub @ .., _, _, _, _, _] => c!(sub, &mut [N], &mut n![] as &mut [N])); - m!(v[..], [_, _, _, _, _, ref mut sub @ ..] => c!(sub, &mut [N], &mut n![] as &mut [N])); - m!(vc[..], [x, .., y] => c!((x, y), (u8, u8), (0, 4))); - - // Matching slices using default binding modes (&): - let [..] = &v[..]; // Always matches. - m!(&v[..], [N(0), sub @ .., N(4)] => c!(sub, &[N], n![1, 2, 3])); - m!(&v[..], [N(0), sub @ ..] => c!(sub, &[N], n![1, 2, 3, 4])); - m!(&v[..], [sub @ .., N(4)] => c!(sub, &[N], n![0, 1, 2, 3])); - m!(&v[..], [sub @ .., _, _, _, _, _] => c!(sub, &[N], &n![] as &[N])); - m!(&v[..], [_, _, _, _, _, sub @ ..] => c!(sub, &[N], &n![] as &[N])); - m!(&vc[..], [x, .., y] => c!((x, y), (&u8, &u8), (&0, &4))); - - // Matching slices using default binding modes (&mut): - let [..] = &mut v[..]; // Always matches. - m!(&mut v[..], [N(0), sub @ .., N(4)] => c!(sub, &mut [N], n![1, 2, 3])); - m!(&mut v[..], [N(0), sub @ ..] => c!(sub, &mut [N], n![1, 2, 3, 4])); - m!(&mut v[..], [sub @ .., N(4)] => c!(sub, &mut [N], n![0, 1, 2, 3])); - m!(&mut v[..], [sub @ .., _, _, _, _, _] => c!(sub, &mut [N], &mut n![] as &mut [N])); - m!(&mut v[..], [_, _, _, _, _, sub @ ..] => c!(sub, &mut [N], &mut n![] as &mut [N])); - m!(&mut vc[..], [x, .., y] => c!((x, y), (&mut u8, &mut u8), (&mut 0, &mut 4))); - - // == Arrays == - let mut v = n![0, 1, 2, 3, 4]; - let vc = [0, 1, 2, 3, 4]; - - // Matching arrays by value: - m!(v.clone(), [N(0), sub @ .., N(4)] => c!(sub, [N; 3], n![1, 2, 3])); - m!(v.clone(), [N(0), sub @ ..] => c!(sub, [N; 4], n![1, 2, 3, 4])); - m!(v.clone(), [sub @ .., N(4)] => c!(sub, [N; 4], n![0, 1, 2, 3])); - m!(v.clone(), [sub @ .., _, _, _, _, _] => c!(sub, [N; 0], n![] as [N; 0])); - m!(v.clone(), [_, _, _, _, _, sub @ ..] => c!(sub, [N; 0], n![] as [N; 0])); - m!(v.clone(), [x, .., y] => c!((x, y), (N, N), (N(0), N(4)))); - m!(v.clone(), [..] => ()); - - // Matching arrays by ref patterns: - m!(v, [N(0), ref sub @ .., N(4)] => c!(sub, &[N; 3], &n![1, 2, 3])); - m!(v, [N(0), ref sub @ ..] => c!(sub, &[N; 4], &n![1, 2, 3, 4])); - m!(v, [ref sub @ .., N(4)] => c!(sub, &[N; 4], &n![0, 1, 2, 3])); - m!(v, [ref sub @ .., _, _, _, _, _] => c!(sub, &[N; 0], &n![] as &[N; 0])); - m!(v, [_, _, _, _, _, ref sub @ ..] => c!(sub, &[N; 0], &n![] as &[N; 0])); - m!(vc, [x, .., y] => c!((x, y), (u8, u8), (0, 4))); - - // Matching arrays by ref mut patterns: - m!(v, [N(0), ref mut sub @ .., N(4)] => c!(sub, &mut [N; 3], &mut n![1, 2, 3])); - m!(v, [N(0), ref mut sub @ ..] => c!(sub, &mut [N; 4], &mut n![1, 2, 3, 4])); - m!(v, [ref mut sub @ .., N(4)] => c!(sub, &mut [N; 4], &mut n![0, 1, 2, 3])); - m!(v, [ref mut sub @ .., _, _, _, _, _] => c!(sub, &mut [N; 0], &mut n![] as &mut [N; 0])); - m!(v, [_, _, _, _, _, ref mut sub @ ..] => c!(sub, &mut [N; 0], &mut n![] as &mut [N; 0])); - - // Matching arrays by default binding modes (&): - m!(&v, [N(0), sub @ .., N(4)] => c!(sub, &[N; 3], &n![1, 2, 3])); - m!(&v, [N(0), sub @ ..] => c!(sub, &[N; 4], &n![1, 2, 3, 4])); - m!(&v, [sub @ .., N(4)] => c!(sub, &[N; 4], &n![0, 1, 2, 3])); - m!(&v, [sub @ .., _, _, _, _, _] => c!(sub, &[N; 0], &n![] as &[N; 0])); - m!(&v, [_, _, _, _, _, sub @ ..] => c!(sub, &[N; 0], &n![] as &[N; 0])); - m!(&v, [..] => ()); - m!(&v, [x, .., y] => c!((x, y), (&N, &N), (&N(0), &N(4)))); - - // Matching arrays by default binding modes (&mut): - m!(&mut v, [N(0), sub @ .., N(4)] => c!(sub, &mut [N; 3], &mut n![1, 2, 3])); - m!(&mut v, [N(0), sub @ ..] => c!(sub, &mut [N; 4], &mut n![1, 2, 3, 4])); - m!(&mut v, [sub @ .., N(4)] => c!(sub, &mut [N; 4], &mut n![0, 1, 2, 3])); - m!(&mut v, [sub @ .., _, _, _, _, _] => c!(sub, &mut [N; 0], &mut n![] as &[N; 0])); - m!(&mut v, [_, _, _, _, _, sub @ ..] => c!(sub, &mut [N; 0], &mut n![] as &[N; 0])); - m!(&mut v, [..] => ()); - m!(&mut v, [x, .., y] => c!((x, y), (&mut N, &mut N), (&mut N(0), &mut N(4)))); -} - -#[test] -fn test_chunk_by() { - let slice = &[1, 1, 1, 3, 3, 2, 2, 2, 1, 0]; - - let mut iter = slice.chunk_by(|a, b| a == b); - assert_eq!(iter.next(), Some(&[1, 1, 1][..])); - assert_eq!(iter.next(), Some(&[3, 3][..])); - assert_eq!(iter.next(), Some(&[2, 2, 2][..])); - assert_eq!(iter.next(), Some(&[1][..])); - assert_eq!(iter.next(), Some(&[0][..])); - assert_eq!(iter.next(), None); - - let mut iter = slice.chunk_by(|a, b| a == b); - assert_eq!(iter.next_back(), Some(&[0][..])); - assert_eq!(iter.next_back(), Some(&[1][..])); - assert_eq!(iter.next_back(), Some(&[2, 2, 2][..])); - assert_eq!(iter.next_back(), Some(&[3, 3][..])); - assert_eq!(iter.next_back(), Some(&[1, 1, 1][..])); - assert_eq!(iter.next_back(), None); - - let mut iter = slice.chunk_by(|a, b| a == b); - assert_eq!(iter.next(), Some(&[1, 1, 1][..])); - assert_eq!(iter.next_back(), Some(&[0][..])); - assert_eq!(iter.next(), Some(&[3, 3][..])); - assert_eq!(iter.next_back(), Some(&[1][..])); - assert_eq!(iter.next(), Some(&[2, 2, 2][..])); - assert_eq!(iter.next_back(), None); -} - -#[test] -fn test_chunk_by_mut() { - let slice = &mut [1, 1, 1, 3, 3, 2, 2, 2, 1, 0]; - - let mut iter = slice.chunk_by_mut(|a, b| a == b); - assert_eq!(iter.next(), Some(&mut [1, 1, 1][..])); - assert_eq!(iter.next(), Some(&mut [3, 3][..])); - assert_eq!(iter.next(), Some(&mut [2, 2, 2][..])); - assert_eq!(iter.next(), Some(&mut [1][..])); - assert_eq!(iter.next(), Some(&mut [0][..])); - assert_eq!(iter.next(), None); - - let mut iter = slice.chunk_by_mut(|a, b| a == b); - assert_eq!(iter.next_back(), Some(&mut [0][..])); - assert_eq!(iter.next_back(), Some(&mut [1][..])); - assert_eq!(iter.next_back(), Some(&mut [2, 2, 2][..])); - assert_eq!(iter.next_back(), Some(&mut [3, 3][..])); - assert_eq!(iter.next_back(), Some(&mut [1, 1, 1][..])); - assert_eq!(iter.next_back(), None); - - let mut iter = slice.chunk_by_mut(|a, b| a == b); - assert_eq!(iter.next(), Some(&mut [1, 1, 1][..])); - assert_eq!(iter.next_back(), Some(&mut [0][..])); - assert_eq!(iter.next(), Some(&mut [3, 3][..])); - assert_eq!(iter.next_back(), Some(&mut [1][..])); - assert_eq!(iter.next(), Some(&mut [2, 2, 2][..])); - assert_eq!(iter.next_back(), None); -} diff --git a/library/alloc/tests/sort/ffi_types.rs b/library/alloc/tests/sort/ffi_types.rs deleted file mode 100644 index 11515ea4769..00000000000 --- a/library/alloc/tests/sort/ffi_types.rs +++ /dev/null @@ -1,82 +0,0 @@ -use std::cmp::Ordering; - -// Very large stack value. -#[repr(C)] -#[derive(PartialEq, Eq, Debug, Clone)] -pub struct FFIOneKibiByte { - values: [i64; 128], -} - -impl FFIOneKibiByte { - pub fn new(val: i32) -> Self { - let mut values = [0i64; 128]; - let mut val_i64 = val as i64; - - for elem in &mut values { - *elem = val_i64; - val_i64 = std::hint::black_box(val_i64 + 1); - } - Self { values } - } - - fn as_i64(&self) -> i64 { - self.values[11] + self.values[55] + self.values[77] - } -} - -impl PartialOrd for FFIOneKibiByte { - fn partial_cmp(&self, other: &Self) -> Option<Ordering> { - Some(self.cmp(other)) - } -} - -impl Ord for FFIOneKibiByte { - fn cmp(&self, other: &Self) -> Ordering { - self.as_i64().cmp(&other.as_i64()) - } -} - -// 16 byte stack value, with more expensive comparison. -#[repr(C)] -#[derive(PartialEq, Debug, Clone, Copy)] -pub struct F128 { - x: f64, - y: f64, -} - -impl F128 { - pub fn new(val: i32) -> Self { - let val_f = (val as f64) + (i32::MAX as f64) + 10.0; - - let x = val_f + 0.1; - let y = val_f.log(4.1); - - assert!(y < x); - assert!(x.is_normal() && y.is_normal()); - - Self { x, y } - } -} - -// This is kind of hacky, but we know we only have normal comparable floats in there. -impl Eq for F128 {} - -impl PartialOrd for F128 { - fn partial_cmp(&self, other: &Self) -> Option<Ordering> { - Some(self.cmp(other)) - } -} - -// Goal is similar code-gen between Rust and C++ -// - Rust https://godbolt.org/z/3YM3xenPP -// - C++ https://godbolt.org/z/178M6j1zz -impl Ord for F128 { - fn cmp(&self, other: &Self) -> Ordering { - // Simulate expensive comparison function. - let this_div = self.x / self.y; - let other_div = other.x / other.y; - - // SAFETY: We checked in the ctor that both are normal. - unsafe { this_div.partial_cmp(&other_div).unwrap_unchecked() } - } -} diff --git a/library/alloc/tests/sort/known_good_stable_sort.rs b/library/alloc/tests/sort/known_good_stable_sort.rs deleted file mode 100644 index 2df89146253..00000000000 --- a/library/alloc/tests/sort/known_good_stable_sort.rs +++ /dev/null @@ -1,192 +0,0 @@ -// This module implements a known good stable sort implementation that helps provide better error -// messages when the correctness tests fail, we can't use the stdlib sort functions because we are -// testing them for correctness. -// -// Based on https://github.com/voultapher/tiny-sort-rs. - -use alloc::alloc::{Layout, alloc, dealloc}; -use std::ptr; - -/// Sort `v` preserving initial order of equal elements. -/// -/// - Guaranteed O(N * log(N)) worst case perf -/// - No adaptiveness -/// - Branch miss-prediction not affected by outcome of comparison function -/// - Uses `v.len()` auxiliary memory. -/// -/// If `T: Ord` does not implement a total order the resulting order is -/// unspecified. All original elements will remain in `v` and any possible modifications via -/// interior mutability will be observable. Same is true if `T: Ord` panics. -/// -/// Panics if allocating the auxiliary memory fails. -#[inline(always)] -pub fn sort<T: Ord>(v: &mut [T]) { - stable_sort(v, |a, b| a.lt(b)) -} - -#[inline(always)] -fn stable_sort<T, F: FnMut(&T, &T) -> bool>(v: &mut [T], mut is_less: F) { - if size_of::<T>() == 0 { - return; - } - - let len = v.len(); - - // Inline the check for len < 2. This happens a lot, instrumenting the Rust compiler suggests - // len < 2 accounts for 94% of its calls to `slice::sort`. - if len < 2 { - return; - } - - // SAFETY: We checked that len is > 0 and that T is not a ZST. - unsafe { - mergesort_main(v, &mut is_less); - } -} - -/// The core logic should not be inlined. -/// -/// SAFETY: The caller has to ensure that len is > 0 and that T is not a ZST. -#[inline(never)] -unsafe fn mergesort_main<T, F: FnMut(&T, &T) -> bool>(v: &mut [T], is_less: &mut F) { - // While it would be nice to have a merge implementation that only requires N / 2 auxiliary - // memory. Doing so would make the merge implementation significantly more complex and - - // SAFETY: See function safety description. - let buf = unsafe { BufGuard::new(v.len()) }; - - // SAFETY: `scratch` has space for `v.len()` writes. And does not alias `v`. - unsafe { - mergesort_core(v, buf.buf_ptr.as_ptr(), is_less); - } -} - -/// Tiny recursive top-down merge sort optimized for binary size. It has no adaptiveness whatsoever, -/// no run detection, etc. -/// -/// Buffer as pointed to by `scratch` must have space for `v.len()` writes. And must not alias `v`. -#[inline(always)] -unsafe fn mergesort_core<T, F: FnMut(&T, &T) -> bool>( - v: &mut [T], - scratch_ptr: *mut T, - is_less: &mut F, -) { - let len = v.len(); - - if len > 2 { - // SAFETY: `mid` is guaranteed in-bounds. And caller has to ensure that `scratch_ptr` can - // hold `v.len()` values. - unsafe { - let mid = len / 2; - // Sort the left half recursively. - mergesort_core(v.get_unchecked_mut(..mid), scratch_ptr, is_less); - // Sort the right half recursively. - mergesort_core(v.get_unchecked_mut(mid..), scratch_ptr, is_less); - // Combine the two halves. - merge(v, scratch_ptr, is_less, mid); - } - } else if len == 2 { - if is_less(&v[1], &v[0]) { - v.swap(0, 1); - } - } -} - -/// Branchless merge function. -/// -/// SAFETY: The caller must ensure that `scratch_ptr` is valid for `v.len()` writes. And that mid is -/// in-bounds. -#[inline(always)] -unsafe fn merge<T, F>(v: &mut [T], scratch_ptr: *mut T, is_less: &mut F, mid: usize) -where - F: FnMut(&T, &T) -> bool, -{ - let len = v.len(); - debug_assert!(mid > 0 && mid < len); - - let len = v.len(); - - // Indexes to track the positions while merging. - let mut l = 0; - let mut r = mid; - - // SAFETY: No matter what the result of is_less is we check that l and r remain in-bounds and if - // is_less panics the original elements remain in `v`. - unsafe { - let arr_ptr = v.as_ptr(); - - for i in 0..len { - let left_ptr = arr_ptr.add(l); - let right_ptr = arr_ptr.add(r); - - let is_lt = !is_less(&*right_ptr, &*left_ptr); - let copy_ptr = if is_lt { left_ptr } else { right_ptr }; - ptr::copy_nonoverlapping(copy_ptr, scratch_ptr.add(i), 1); - - l += is_lt as usize; - r += !is_lt as usize; - - // As long as neither side is exhausted merge left and right elements. - if ((l == mid) as u8 + (r == len) as u8) != 0 { - break; - } - } - - // The left or right side is exhausted, drain the right side in one go. - let copy_ptr = if l == mid { arr_ptr.add(r) } else { arr_ptr.add(l) }; - let i = l + (r - mid); - ptr::copy_nonoverlapping(copy_ptr, scratch_ptr.add(i), len - i); - - // Now that scratch_ptr holds the full merged content, write it back on-top of v. - ptr::copy_nonoverlapping(scratch_ptr, v.as_mut_ptr(), len); - } -} - -// SAFETY: The caller has to ensure that Option is Some, UB otherwise. -unsafe fn unwrap_unchecked<T>(opt_val: Option<T>) -> T { - match opt_val { - Some(val) => val, - None => { - // SAFETY: See function safety description. - unsafe { - core::hint::unreachable_unchecked(); - } - } - } -} - -// Extremely basic versions of Vec. -// Their use is super limited and by having the code here, it allows reuse between the sort -// implementations. -struct BufGuard<T> { - buf_ptr: ptr::NonNull<T>, - capacity: usize, -} - -impl<T> BufGuard<T> { - // SAFETY: The caller has to ensure that len is not 0 and that T is not a ZST. - unsafe fn new(len: usize) -> Self { - debug_assert!(len > 0 && size_of::<T>() > 0); - - // SAFETY: See function safety description. - let layout = unsafe { unwrap_unchecked(Layout::array::<T>(len).ok()) }; - - // SAFETY: We checked that T is not a ZST. - let buf_ptr = unsafe { alloc(layout) as *mut T }; - - if buf_ptr.is_null() { - panic!("allocation failure"); - } - - Self { buf_ptr: ptr::NonNull::new(buf_ptr).unwrap(), capacity: len } - } -} - -impl<T> Drop for BufGuard<T> { - fn drop(&mut self) { - // SAFETY: We checked that T is not a ZST. - unsafe { - dealloc(self.buf_ptr.as_ptr() as *mut u8, Layout::array::<T>(self.capacity).unwrap()); - } - } -} diff --git a/library/alloc/tests/sort/mod.rs b/library/alloc/tests/sort/mod.rs deleted file mode 100644 index 0e2494ca9d3..00000000000 --- a/library/alloc/tests/sort/mod.rs +++ /dev/null @@ -1,17 +0,0 @@ -pub trait Sort { - fn name() -> String; - - fn sort<T>(v: &mut [T]) - where - T: Ord; - - fn sort_by<T, F>(v: &mut [T], compare: F) - where - F: FnMut(&T, &T) -> std::cmp::Ordering; -} - -mod ffi_types; -mod known_good_stable_sort; -mod patterns; -mod tests; -mod zipf; diff --git a/library/alloc/tests/sort/patterns.rs b/library/alloc/tests/sort/patterns.rs deleted file mode 100644 index 0f1ec664d3d..00000000000 --- a/library/alloc/tests/sort/patterns.rs +++ /dev/null @@ -1,211 +0,0 @@ -use std::env; -use std::str::FromStr; -use std::sync::OnceLock; - -use rand::distr::Uniform; -use rand::prelude::*; -use rand_xorshift::XorShiftRng; - -use crate::sort::zipf::ZipfDistribution; - -/// Provides a set of patterns useful for testing and benchmarking sorting algorithms. -/// Currently limited to i32 values. - -// --- Public --- - -pub fn random(len: usize) -> Vec<i32> { - // . - // : . : : - // :.:::.:: - - random_vec(len) -} - -pub fn random_uniform<R>(len: usize, range: R) -> Vec<i32> -where - Uniform<i32>: TryFrom<R, Error: std::fmt::Debug>, -{ - // :.:.:.:: - - let mut rng: XorShiftRng = rand::SeedableRng::seed_from_u64(get_or_init_rand_seed()); - - // Abstracting over ranges in Rust :( - let dist = Uniform::try_from(range).unwrap(); - (0..len).map(|_| dist.sample(&mut rng)).collect() -} - -pub fn random_zipf(len: usize, exponent: f64) -> Vec<i32> { - // https://en.wikipedia.org/wiki/Zipf's_law - - let mut rng: XorShiftRng = rand::SeedableRng::seed_from_u64(get_or_init_rand_seed()); - - // Abstracting over ranges in Rust :( - let dist = ZipfDistribution::new(len, exponent).unwrap(); - (0..len).map(|_| dist.sample(&mut rng) as i32).collect() -} - -pub fn random_sorted(len: usize, sorted_percent: f64) -> Vec<i32> { - // .: - // .:::. : - // .::::::.:: - // [----][--] - // ^ ^ - // | | - // sorted | - // unsorted - - // Simulate pre-existing sorted slice, where len - sorted_percent are the new unsorted values - // and part of the overall distribution. - let mut v = random_vec(len); - let sorted_len = ((len as f64) * (sorted_percent / 100.0)).round() as usize; - - v[0..sorted_len].sort_unstable(); - - v -} - -pub fn all_equal(len: usize) -> Vec<i32> { - // ...... - // :::::: - - (0..len).map(|_| 66).collect::<Vec<_>>() -} - -pub fn ascending(len: usize) -> Vec<i32> { - // .: - // .::: - // .::::: - - (0..len as i32).collect::<Vec<_>>() -} - -pub fn descending(len: usize) -> Vec<i32> { - // :. - // :::. - // :::::. - - (0..len as i32).rev().collect::<Vec<_>>() -} - -pub fn saw_mixed(len: usize, saw_count: usize) -> Vec<i32> { - // :. :. .::. .: - // :::.:::..::::::..::: - - if len == 0 { - return Vec::new(); - } - - let mut vals = random_vec(len); - let chunks_size = len / saw_count.max(1); - let saw_directions = random_uniform((len / chunks_size) + 1, 0..=1); - - for (i, chunk) in vals.chunks_mut(chunks_size).enumerate() { - if saw_directions[i] == 0 { - chunk.sort_unstable(); - } else if saw_directions[i] == 1 { - chunk.sort_unstable_by_key(|&e| std::cmp::Reverse(e)); - } else { - unreachable!(); - } - } - - vals -} - -pub fn saw_mixed_range(len: usize, range: std::ops::Range<usize>) -> Vec<i32> { - // :. - // :. :::. .::. .: - // :::.:::::..::::::..:.::: - - // ascending and descending randomly picked, with length in `range`. - - if len == 0 { - return Vec::new(); - } - - let mut vals = random_vec(len); - - let max_chunks = len / range.start; - let saw_directions = random_uniform(max_chunks + 1, 0..=1); - let chunk_sizes = random_uniform(max_chunks + 1, (range.start as i32)..(range.end as i32)); - - let mut i = 0; - let mut l = 0; - while l < len { - let chunk_size = chunk_sizes[i] as usize; - let chunk_end = std::cmp::min(l + chunk_size, len); - let chunk = &mut vals[l..chunk_end]; - - if saw_directions[i] == 0 { - chunk.sort_unstable(); - } else if saw_directions[i] == 1 { - chunk.sort_unstable_by_key(|&e| std::cmp::Reverse(e)); - } else { - unreachable!(); - } - - i += 1; - l += chunk_size; - } - - vals -} - -pub fn pipe_organ(len: usize) -> Vec<i32> { - // .:. - // .:::::. - - let mut vals = random_vec(len); - - let first_half = &mut vals[0..(len / 2)]; - first_half.sort_unstable(); - - let second_half = &mut vals[(len / 2)..len]; - second_half.sort_unstable_by_key(|&e| std::cmp::Reverse(e)); - - vals -} - -pub fn get_or_init_rand_seed() -> u64 { - *SEED_VALUE.get_or_init(|| { - env::var("OVERRIDE_SEED") - .ok() - .map(|seed| u64::from_str(&seed).unwrap()) - .unwrap_or_else(rand_root_seed) - }) -} - -// --- Private --- - -static SEED_VALUE: OnceLock<u64> = OnceLock::new(); - -#[cfg(not(miri))] -fn rand_root_seed() -> u64 { - // Other test code hashes `panic::Location::caller()` and constructs a seed from that, in these - // tests we want to have a fuzzer like exploration of the test space, if we used the same caller - // based construction we would always test the same. - // - // Instead we use the seconds since UNIX epoch / 10, given CI log output this value should be - // reasonably easy to re-construct. - - use std::time::{SystemTime, UNIX_EPOCH}; - - let epoch_seconds = SystemTime::now().duration_since(UNIX_EPOCH).unwrap().as_secs(); - - epoch_seconds / 10 -} - -#[cfg(miri)] -fn rand_root_seed() -> u64 { - // Miri is usually run with isolation with gives us repeatability but also permutations based on - // other code that runs before. - use core::hash::{BuildHasher, Hash, Hasher}; - let mut hasher = std::hash::RandomState::new().build_hasher(); - core::panic::Location::caller().hash(&mut hasher); - hasher.finish() -} - -fn random_vec(len: usize) -> Vec<i32> { - let mut rng: XorShiftRng = rand::SeedableRng::seed_from_u64(get_or_init_rand_seed()); - (0..len).map(|_| rng.random::<i32>()).collect() -} diff --git a/library/alloc/tests/sort/tests.rs b/library/alloc/tests/sort/tests.rs deleted file mode 100644 index d321f8df518..00000000000 --- a/library/alloc/tests/sort/tests.rs +++ /dev/null @@ -1,1240 +0,0 @@ -use std::cell::Cell; -use std::cmp::Ordering; -use std::fmt::Debug; -use std::panic::{self, AssertUnwindSafe}; -use std::rc::Rc; -use std::{env, fs}; - -use crate::sort::ffi_types::{F128, FFIOneKibiByte}; -use crate::sort::{Sort, known_good_stable_sort, patterns}; - -#[cfg(miri)] -const TEST_LENGTHS: &[usize] = &[2, 3, 4, 7, 10, 15, 20, 24, 33, 50, 100, 171, 300]; - -// node.js gives out of memory error to use with length 1_100_000 -#[cfg(all(not(miri), target_os = "emscripten"))] -const TEST_LENGTHS: &[usize] = &[ - 2, 3, 4, 5, 6, 7, 8, 9, 10, 15, 16, 17, 20, 24, 30, 32, 33, 35, 50, 100, 200, 500, 1_000, - 2_048, 5_000, 10_000, 100_000, -]; - -#[cfg(all(not(miri), not(target_os = "emscripten")))] -const TEST_LENGTHS: &[usize] = &[ - 2, 3, 4, 5, 6, 7, 8, 9, 10, 15, 16, 17, 20, 24, 30, 32, 33, 35, 50, 100, 200, 500, 1_000, - 2_048, 5_000, 10_000, 100_000, 1_100_000, -]; - -fn check_is_sorted<T: Ord + Clone + Debug, S: Sort>(v: &mut [T]) { - let seed = patterns::get_or_init_rand_seed(); - - let is_small_test = v.len() <= 100; - let v_orig = v.to_vec(); - - <S as Sort>::sort(v); - - assert_eq!(v.len(), v_orig.len()); - - for window in v.windows(2) { - if window[0] > window[1] { - let mut known_good_sorted_vec = v_orig.clone(); - known_good_stable_sort::sort(known_good_sorted_vec.as_mut_slice()); - - if is_small_test { - eprintln!("Original: {:?}", v_orig); - eprintln!("Expected: {:?}", known_good_sorted_vec); - eprintln!("Got: {:?}", v); - } else { - if env::var("WRITE_LARGE_FAILURE").is_ok() { - // Large arrays output them as files. - let original_name = format!("original_{}.txt", seed); - let std_name = format!("known_good_sorted_{}.txt", seed); - let testsort_name = format!("{}_sorted_{}.txt", S::name(), seed); - - fs::write(&original_name, format!("{:?}", v_orig)).unwrap(); - fs::write(&std_name, format!("{:?}", known_good_sorted_vec)).unwrap(); - fs::write(&testsort_name, format!("{:?}", v)).unwrap(); - - eprintln!( - "Failed comparison, see files {original_name}, {std_name}, and {testsort_name}" - ); - } else { - eprintln!( - "Failed comparison, re-run with WRITE_LARGE_FAILURE env var set, to get output." - ); - } - } - - panic!("Test assertion failed!") - } - } -} - -fn test_is_sorted<T: Ord + Clone + Debug, S: Sort>( - test_len: usize, - map_fn: impl Fn(i32) -> T, - pattern_fn: impl Fn(usize) -> Vec<i32>, -) { - let mut test_data: Vec<T> = pattern_fn(test_len).into_iter().map(map_fn).collect(); - check_is_sorted::<T, S>(test_data.as_mut_slice()); -} - -trait DynTrait: Debug { - fn get_val(&self) -> i32; -} - -#[derive(Clone, Debug, PartialEq, Eq, PartialOrd, Ord)] -struct DynValA { - value: i32, -} - -#[derive(Clone, Debug, PartialEq, Eq, PartialOrd, Ord)] -struct DynValB { - value: u64, -} - -impl DynTrait for DynValA { - fn get_val(&self) -> i32 { - self.value - } -} -impl DynTrait for DynValB { - fn get_val(&self) -> i32 { - let bytes = self.value.to_ne_bytes(); - i32::from_ne_bytes([bytes[0], bytes[1], bytes[6], bytes[7]]) - } -} - -impl PartialOrd for dyn DynTrait { - fn partial_cmp(&self, other: &Self) -> Option<Ordering> { - Some(self.cmp(other)) - } -} - -impl Ord for dyn DynTrait { - fn cmp(&self, other: &Self) -> Ordering { - self.get_val().cmp(&other.get_val()) - } -} - -impl PartialEq for dyn DynTrait { - fn eq(&self, other: &Self) -> bool { - self.get_val() == other.get_val() - } -} - -impl Eq for dyn DynTrait {} - -fn shift_i32_to_u32(val: i32) -> u32 { - (val as i64 + (i32::MAX as i64 + 1)) as u32 -} - -fn reverse_shift_i32_to_u32(val: u32) -> i32 { - (val as i64 - (i32::MAX as i64 + 1)) as i32 -} - -fn extend_i32_to_u64(val: i32) -> u64 { - // Extends the value into the 64 bit range, - // while preserving input order. - (shift_i32_to_u32(val) as u64) * i32::MAX as u64 -} - -fn extend_i32_to_u128(val: i32) -> u128 { - // Extends the value into the 64 bit range, - // while preserving input order. - (shift_i32_to_u32(val) as u128) * i64::MAX as u128 -} - -fn dyn_trait_from_i32(val: i32) -> Rc<dyn DynTrait> { - if val % 2 == 0 { - Rc::new(DynValA { value: val }) - } else { - Rc::new(DynValB { value: extend_i32_to_u64(val) }) - } -} - -fn i32_from_i32(val: i32) -> i32 { - val -} - -fn i32_from_i32_ref(val: &i32) -> i32 { - *val -} - -fn string_from_i32(val: i32) -> String { - format!("{:010}", shift_i32_to_u32(val)) -} - -fn i32_from_string(val: &String) -> i32 { - reverse_shift_i32_to_u32(val.parse::<u32>().unwrap()) -} - -fn cell_i32_from_i32(val: i32) -> Cell<i32> { - Cell::new(val) -} - -fn i32_from_cell_i32(val: &Cell<i32>) -> i32 { - val.get() -} - -fn calc_comps_required<T, S: Sort>(v: &mut [T], mut cmp_fn: impl FnMut(&T, &T) -> Ordering) -> u32 { - let mut comp_counter = 0u32; - - <S as Sort>::sort_by(v, |a, b| { - comp_counter += 1; - - cmp_fn(a, b) - }); - - comp_counter -} - -#[derive(PartialEq, Eq, Debug, Clone)] -#[repr(C)] -struct CompCount { - val: i32, - comp_count: Cell<u32>, -} - -impl CompCount { - fn new(val: i32) -> Self { - Self { val, comp_count: Cell::new(0) } - } -} - -/// Generates $base_name_pattern_name_impl functions calling the test_fns for all test_len. -macro_rules! gen_sort_test_fns { - ( - $base_name:ident, - $test_fn:expr, - $test_lengths:expr, - [$(($pattern_name:ident, $pattern_fn:expr)),* $(,)?] $(,)? - ) => { - $(fn ${concat($base_name, _, $pattern_name, _impl)}<S: Sort>() { - for test_len in $test_lengths { - $test_fn(*test_len, $pattern_fn); - } - })* - }; -} - -/// Generates $base_name_pattern_name_impl functions calling the test_fns for all test_len, -/// with a default set of patterns that can be extended by the caller. -macro_rules! gen_sort_test_fns_with_default_patterns { - ( - $base_name:ident, - $test_fn:expr, - $test_lengths:expr, - [$(($pattern_name:ident, $pattern_fn:expr)),* $(,)?] $(,)? - ) => { - gen_sort_test_fns!( - $base_name, - $test_fn, - $test_lengths, - [ - (random, patterns::random), - (random_z1, |len| patterns::random_zipf(len, 1.0)), - (random_d2, |len| patterns::random_uniform(len, 0..2)), - (random_d20, |len| patterns::random_uniform(len, 0..16)), - (random_s95, |len| patterns::random_sorted(len, 95.0)), - (ascending, patterns::ascending), - (descending, patterns::descending), - (saw_mixed, |len| patterns::saw_mixed( - len, - ((len as f64).log2().round()) as usize - )), - $(($pattern_name, $pattern_fn),)* - ] - ); - }; -} - -/// Generates $base_name_type_pattern_name_impl functions calling the test_fns for all test_len for -/// three types that cover the core specialization differences in the sort implementations, with a -/// default set of patterns that can be extended by the caller. -macro_rules! gen_sort_test_fns_with_default_patterns_3_ty { - ( - $base_name:ident, - $test_fn:ident, - [$(($pattern_name:ident, $pattern_fn:expr)),* $(,)?] $(,)? - ) => { - gen_sort_test_fns_with_default_patterns!( - ${concat($base_name, _i32)}, - |len, pattern_fn| $test_fn::<i32, S>(len, i32_from_i32, i32_from_i32_ref, pattern_fn), - &TEST_LENGTHS[..TEST_LENGTHS.len() - 2], - [$(($pattern_name, $pattern_fn),)*], - ); - - gen_sort_test_fns_with_default_patterns!( - ${concat($base_name, _cell_i32)}, - |len, pattern_fn| $test_fn::<Cell<i32>, S>(len, cell_i32_from_i32, i32_from_cell_i32, pattern_fn), - &TEST_LENGTHS[..TEST_LENGTHS.len() - 3], - [$(($pattern_name, $pattern_fn),)*], - ); - - gen_sort_test_fns_with_default_patterns!( - ${concat($base_name, _string)}, - |len, pattern_fn| $test_fn::<String, S>(len, string_from_i32, i32_from_string, pattern_fn), - &TEST_LENGTHS[..TEST_LENGTHS.len() - 3], - [$(($pattern_name, $pattern_fn),)*], - ); - }; -} - -// --- TESTS --- - -pub fn basic_impl<S: Sort>() { - check_is_sorted::<i32, S>(&mut []); - check_is_sorted::<(), S>(&mut []); - check_is_sorted::<(), S>(&mut [()]); - check_is_sorted::<(), S>(&mut [(), ()]); - check_is_sorted::<(), S>(&mut [(), (), ()]); - check_is_sorted::<i32, S>(&mut []); - check_is_sorted::<i32, S>(&mut [77]); - check_is_sorted::<i32, S>(&mut [2, 3]); - check_is_sorted::<i32, S>(&mut [2, 3, 6]); - check_is_sorted::<i32, S>(&mut [2, 3, 99, 6]); - check_is_sorted::<i32, S>(&mut [2, 7709, 400, 90932]); - check_is_sorted::<i32, S>(&mut [15, -1, 3, -1, -3, -1, 7]); -} - -fn fixed_seed_impl<S: Sort>() { - let fixed_seed_a = patterns::get_or_init_rand_seed(); - let fixed_seed_b = patterns::get_or_init_rand_seed(); - - assert_eq!(fixed_seed_a, fixed_seed_b); -} - -fn fixed_seed_rand_vec_prefix_impl<S: Sort>() { - let vec_rand_len_5 = patterns::random(5); - let vec_rand_len_7 = patterns::random(7); - - assert_eq!(vec_rand_len_5, vec_rand_len_7[..5]); -} - -fn int_edge_impl<S: Sort>() { - // Ensure that the sort can handle integer edge cases. - check_is_sorted::<i32, S>(&mut [i32::MIN, i32::MAX]); - check_is_sorted::<i32, S>(&mut [i32::MAX, i32::MIN]); - check_is_sorted::<i32, S>(&mut [i32::MIN, 3]); - check_is_sorted::<i32, S>(&mut [i32::MIN, -3]); - check_is_sorted::<i32, S>(&mut [i32::MIN, -3, i32::MAX]); - check_is_sorted::<i32, S>(&mut [i32::MIN, -3, i32::MAX, i32::MIN, 5]); - check_is_sorted::<i32, S>(&mut [i32::MAX, 3, i32::MIN, 5, i32::MIN, -3, 60, 200, 50, 7, 10]); - - check_is_sorted::<u64, S>(&mut [u64::MIN, u64::MAX]); - check_is_sorted::<u64, S>(&mut [u64::MAX, u64::MIN]); - check_is_sorted::<u64, S>(&mut [u64::MIN, 3]); - check_is_sorted::<u64, S>(&mut [u64::MIN, u64::MAX - 3]); - check_is_sorted::<u64, S>(&mut [u64::MIN, u64::MAX - 3, u64::MAX]); - check_is_sorted::<u64, S>(&mut [u64::MIN, u64::MAX - 3, u64::MAX, u64::MIN, 5]); - check_is_sorted::<u64, S>(&mut [ - u64::MAX, - 3, - u64::MIN, - 5, - u64::MIN, - u64::MAX - 3, - 60, - 200, - 50, - 7, - 10, - ]); - - let mut large = patterns::random(TEST_LENGTHS[TEST_LENGTHS.len() - 2]); - large.push(i32::MAX); - large.push(i32::MIN); - large.push(i32::MAX); - check_is_sorted::<i32, S>(&mut large); -} - -fn sort_vs_sort_by_impl<S: Sort>() { - // Ensure that sort and sort_by produce the same result. - let mut input_normal = [800, 3, -801, 5, -801, -3, 60, 200, 50, 7, 10]; - let expected = [-801, -801, -3, 3, 5, 7, 10, 50, 60, 200, 800]; - - let mut input_sort_by = input_normal.to_vec(); - - <S as Sort>::sort(&mut input_normal); - <S as Sort>::sort_by(&mut input_sort_by, |a, b| a.cmp(b)); - - assert_eq!(input_normal, expected); - assert_eq!(input_sort_by, expected); -} - -gen_sort_test_fns_with_default_patterns!( - correct_i32, - |len, pattern_fn| test_is_sorted::<i32, S>(len, |val| val, pattern_fn), - TEST_LENGTHS, - [ - (random_d4, |len| patterns::random_uniform(len, 0..4)), - (random_d8, |len| patterns::random_uniform(len, 0..8)), - (random_d311, |len| patterns::random_uniform(len, 0..311)), - (random_d1024, |len| patterns::random_uniform(len, 0..1024)), - (random_z1_03, |len| patterns::random_zipf(len, 1.03)), - (random_z2, |len| patterns::random_zipf(len, 2.0)), - (random_s50, |len| patterns::random_sorted(len, 50.0)), - (narrow, |len| patterns::random_uniform( - len, - 0..=(((len as f64).log2().round()) as i32) * 100 - )), - (all_equal, patterns::all_equal), - (saw_mixed_range, |len| patterns::saw_mixed_range(len, 20..50)), - (pipe_organ, patterns::pipe_organ), - ] -); - -gen_sort_test_fns_with_default_patterns!( - correct_u64, - |len, pattern_fn| test_is_sorted::<u64, S>(len, extend_i32_to_u64, pattern_fn), - TEST_LENGTHS, - [] -); - -gen_sort_test_fns_with_default_patterns!( - correct_u128, - |len, pattern_fn| test_is_sorted::<u128, S>(len, extend_i32_to_u128, pattern_fn), - &TEST_LENGTHS[..TEST_LENGTHS.len() - 2], - [] -); - -gen_sort_test_fns_with_default_patterns!( - correct_cell_i32, - |len, pattern_fn| test_is_sorted::<Cell<i32>, S>(len, Cell::new, pattern_fn), - &TEST_LENGTHS[..TEST_LENGTHS.len() - 2], - [] -); - -gen_sort_test_fns_with_default_patterns!( - correct_string, - |len, pattern_fn| test_is_sorted::<String, S>( - len, - |val| format!("{:010}", shift_i32_to_u32(val)), - pattern_fn - ), - &TEST_LENGTHS[..TEST_LENGTHS.len() - 2], - [] -); - -gen_sort_test_fns_with_default_patterns!( - correct_f128, - |len, pattern_fn| test_is_sorted::<F128, S>(len, F128::new, pattern_fn), - &TEST_LENGTHS[..TEST_LENGTHS.len() - 2], - [] -); - -gen_sort_test_fns_with_default_patterns!( - correct_1k, - |len, pattern_fn| test_is_sorted::<FFIOneKibiByte, S>(len, FFIOneKibiByte::new, pattern_fn), - &TEST_LENGTHS[..TEST_LENGTHS.len() - 2], - [] -); - -// Dyn values are fat pointers, something the implementation might have overlooked. -gen_sort_test_fns_with_default_patterns!( - correct_dyn_val, - |len, pattern_fn| test_is_sorted::<Rc<dyn DynTrait>, S>(len, dyn_trait_from_i32, pattern_fn), - &TEST_LENGTHS[..TEST_LENGTHS.len() - 2], - [] -); - -fn stability_legacy_impl<S: Sort>() { - // This non pattern variant has proven to catch some bugs the pattern version of this function - // doesn't catch, so it remains in conjunction with the other one. - - if <S as Sort>::name().contains("unstable") { - // It would be great to mark the test as skipped, but that isn't possible as of now. - return; - } - - let large_range = if cfg!(miri) { 100..110 } else { 3000..3010 }; - let rounds = if cfg!(miri) { 1 } else { 10 }; - - let rand_vals = patterns::random_uniform(5_000, 0..=9); - let mut rand_idx = 0; - - for len in (2..55).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 = rand_vals[rand_idx]; - rand_idx += 1; - if rand_idx >= rand_vals.len() { - rand_idx = 0; - } - - counts[n as usize] += 1; - i32_tup_as_u64((n, counts[n as usize])) - }) - .collect(); - - let mut v = orig.clone(); - // Only sort on the first element, so an unstable sort - // may mix up the counts. - <S as Sort>::sort_by(&mut v, |a_packed, b_packed| { - let a = i32_tup_from_u64(*a_packed).0; - let b = i32_tup_from_u64(*b_packed).0; - - 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| i32_tup_from_u64(w[0]) <= i32_tup_from_u64(w[1]))); - } - } - - // For cpp_sorts that only support u64 we can pack the two i32 inside a u64. - fn i32_tup_as_u64(val: (i32, i32)) -> u64 { - let a_bytes = val.0.to_le_bytes(); - let b_bytes = val.1.to_le_bytes(); - - u64::from_le_bytes([a_bytes, b_bytes].concat().try_into().unwrap()) - } - - fn i32_tup_from_u64(val: u64) -> (i32, i32) { - let bytes = val.to_le_bytes(); - - let a = i32::from_le_bytes(bytes[0..4].try_into().unwrap()); - let b = i32::from_le_bytes(bytes[4..8].try_into().unwrap()); - - (a, b) - } -} - -fn stability_with_patterns<T: Ord + Clone, S: Sort>( - len: usize, - type_into_fn: impl Fn(i32) -> T, - _type_from_fn: impl Fn(&T) -> i32, - pattern_fn: fn(usize) -> Vec<i32>, -) { - if <S as Sort>::name().contains("unstable") { - // It would be great to mark the test as skipped, but that isn't possible as of now. - return; - } - - let pattern = pattern_fn(len); - - let mut counts = [0i32; 128]; - - // 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<_> = pattern - .iter() - .map(|val| { - let n = val.saturating_abs() % counts.len() as i32; - counts[n as usize] += 1; - (type_into_fn(n), counts[n as usize]) - }) - .collect(); - - let mut v = orig.clone(); - // Only sort on the first element, so an unstable sort - // may mix up the counts. - <S as Sort>::sort(&mut v); - - // 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])); -} - -gen_sort_test_fns_with_default_patterns_3_ty!(stability, stability_with_patterns, []); - -fn observable_is_less<S: Sort>(len: usize, pattern_fn: fn(usize) -> Vec<i32>) { - // This test, tests that every is_less is actually observable. Ie. this can go wrong if a hole - // is created using temporary memory and, the whole is used as comparison but not copied back. - // - // If this is not upheld a custom type + comparison function could yield UB in otherwise safe - // code. Eg T == Mutex<Option<Box<str>>> which replaces the pointer with none in the comparison - // function, which would not be observed in the original slice and would lead to a double free. - - let pattern = pattern_fn(len); - let mut test_input = pattern.into_iter().map(|val| CompCount::new(val)).collect::<Vec<_>>(); - - let mut comp_count_global = 0; - - <S as Sort>::sort_by(&mut test_input, |a, b| { - a.comp_count.replace(a.comp_count.get() + 1); - b.comp_count.replace(b.comp_count.get() + 1); - comp_count_global += 1; - - a.val.cmp(&b.val) - }); - - let total_inner: u64 = test_input.iter().map(|c| c.comp_count.get() as u64).sum(); - - assert_eq!(total_inner, comp_count_global * 2); -} - -gen_sort_test_fns_with_default_patterns!( - observable_is_less, - observable_is_less::<S>, - &TEST_LENGTHS[..TEST_LENGTHS.len() - 2], - [] -); - -fn panic_retain_orig_set<T: Ord + Clone, S: Sort>( - len: usize, - type_into_fn: impl Fn(i32) -> T + Copy, - type_from_fn: impl Fn(&T) -> i32, - pattern_fn: fn(usize) -> Vec<i32>, -) { - let mut test_data: Vec<T> = pattern_fn(len).into_iter().map(type_into_fn).collect(); - - let sum_before: i64 = test_data.iter().map(|x| type_from_fn(x) as i64).sum(); - - // Calculate a specific comparison that should panic. - // Ensure that it can be any of the possible comparisons and that it always panics. - let required_comps = calc_comps_required::<T, S>(&mut test_data.clone(), |a, b| a.cmp(b)); - let panic_threshold = patterns::random_uniform(1, 1..=required_comps as i32)[0] as usize - 1; - - let mut comp_counter = 0; - - let res = panic::catch_unwind(AssertUnwindSafe(|| { - <S as Sort>::sort_by(&mut test_data, |a, b| { - if comp_counter == panic_threshold { - // Make the panic dependent on the test len and some random factor. We want to - // make sure that panicking may also happen when comparing elements a second - // time. - panic!(); - } - comp_counter += 1; - - a.cmp(b) - }); - })); - - assert!(res.is_err()); - - // If the sum before and after don't match, it means the set of elements hasn't remained the - // same. - let sum_after: i64 = test_data.iter().map(|x| type_from_fn(x) as i64).sum(); - assert_eq!(sum_before, sum_after); -} - -gen_sort_test_fns_with_default_patterns_3_ty!(panic_retain_orig_set, panic_retain_orig_set, []); - -fn panic_observable_is_less<S: Sort>(len: usize, pattern_fn: fn(usize) -> Vec<i32>) { - // This test, tests that every is_less is actually observable. Ie. this can go wrong if a hole - // is created using temporary memory and, the whole is used as comparison but not copied back. - // This property must also hold if the user provided comparison panics. - // - // If this is not upheld a custom type + comparison function could yield UB in otherwise safe - // code. Eg T == Mutex<Option<Box<str>>> which replaces the pointer with none in the comparison - // function, which would not be observed in the original slice and would lead to a double free. - - let mut test_input = - pattern_fn(len).into_iter().map(|val| CompCount::new(val)).collect::<Vec<_>>(); - - let sum_before: i64 = test_input.iter().map(|x| x.val as i64).sum(); - - // Calculate a specific comparison that should panic. - // Ensure that it can be any of the possible comparisons and that it always panics. - let required_comps = - calc_comps_required::<CompCount, S>(&mut test_input.clone(), |a, b| a.val.cmp(&b.val)); - - let panic_threshold = patterns::random_uniform(1, 1..=required_comps as i32)[0] as u64 - 1; - - let mut comp_count_global = 0; - - let res = panic::catch_unwind(AssertUnwindSafe(|| { - <S as Sort>::sort_by(&mut test_input, |a, b| { - if comp_count_global == panic_threshold { - // Make the panic dependent on the test len and some random factor. We want to - // make sure that panicking may also happen when comparing elements a second - // time. - panic!(); - } - - a.comp_count.replace(a.comp_count.get() + 1); - b.comp_count.replace(b.comp_count.get() + 1); - comp_count_global += 1; - - a.val.cmp(&b.val) - }); - })); - - assert!(res.is_err()); - - let total_inner: u64 = test_input.iter().map(|c| c.comp_count.get() as u64).sum(); - - assert_eq!(total_inner, comp_count_global * 2); - - // If the sum before and after don't match, it means the set of elements hasn't remained the - // same. - let sum_after: i64 = test_input.iter().map(|x| x.val as i64).sum(); - assert_eq!(sum_before, sum_after); -} - -gen_sort_test_fns_with_default_patterns!( - panic_observable_is_less, - panic_observable_is_less::<S>, - &TEST_LENGTHS[..TEST_LENGTHS.len() - 2], - [] -); - -fn deterministic<T: Ord + Clone + Debug, S: Sort>( - len: usize, - type_into_fn: impl Fn(i32) -> T + Copy, - type_from_fn: impl Fn(&T) -> i32, - pattern_fn: fn(usize) -> Vec<i32>, -) { - // A property similar to stability is deterministic output order. If the entire value is used as - // the comparison key a lack of determinism has no effect. But if only a part of the value is - // used as comparison key, a lack of determinism can manifest itself in the order of values - // considered equal by the comparison predicate. - // - // This test only tests that results are deterministic across runs, it does not test determinism - // on different platforms and with different toolchains. - - let mut test_input = - pattern_fn(len).into_iter().map(|val| type_into_fn(val)).collect::<Vec<_>>(); - - let mut test_input_clone = test_input.clone(); - - let comparison_fn = |a: &T, b: &T| { - let a_i32 = type_from_fn(a); - let b_i32 = type_from_fn(b); - - let a_i32_key_space_reduced = a_i32 % 10_000; - let b_i32_key_space_reduced = b_i32 % 10_000; - - a_i32_key_space_reduced.cmp(&b_i32_key_space_reduced) - }; - - <S as Sort>::sort_by(&mut test_input, comparison_fn); - <S as Sort>::sort_by(&mut test_input_clone, comparison_fn); - - assert_eq!(test_input, test_input_clone); -} - -gen_sort_test_fns_with_default_patterns_3_ty!(deterministic, deterministic, []); - -fn self_cmp<T: Ord + Clone + Debug, S: Sort>( - len: usize, - type_into_fn: impl Fn(i32) -> T + Copy, - _type_from_fn: impl Fn(&T) -> i32, - pattern_fn: fn(usize) -> Vec<i32>, -) { - // It's possible for comparisons to run into problems if the values of `a` and `b` passed into - // the comparison function are the same reference. So this tests that they never are. - - let mut test_input = - pattern_fn(len).into_iter().map(|val| type_into_fn(val)).collect::<Vec<_>>(); - - let comparison_fn = |a: &T, b: &T| { - assert_ne!(a as *const T as usize, b as *const T as usize); - a.cmp(b) - }; - - <S as Sort>::sort_by(&mut test_input, comparison_fn); - - // Check that the output is actually sorted and wasn't stopped by the assert. - for window in test_input.windows(2) { - assert!(window[0] <= window[1]); - } -} - -gen_sort_test_fns_with_default_patterns_3_ty!(self_cmp, self_cmp, []); - -fn violate_ord_retain_orig_set<T: Ord, S: Sort>( - len: usize, - type_into_fn: impl Fn(i32) -> T + Copy, - type_from_fn: impl Fn(&T) -> i32, - pattern_fn: fn(usize) -> Vec<i32>, -) { - // A user may implement Ord incorrectly for a type or violate it by calling sort_by with a - // comparison function that violates Ord with the orderings it returns. Even under such - // circumstances the input must retain its original set of elements. - - // Ord implies a strict total order see https://en.wikipedia.org/wiki/Total_order. - - // Generating random numbers with miri is quite expensive. - let random_orderings_len = if cfg!(miri) { 200 } else { 10_000 }; - - // Make sure we get a good distribution of random orderings, that are repeatable with the seed. - // Just using random_uniform with the same len and range will always yield the same value. - let random_orderings = patterns::random_uniform(random_orderings_len, 0..2); - - let get_random_0_1_or_2 = |random_idx: &mut usize| { - let ridx = *random_idx; - *random_idx += 1; - if ridx + 1 == random_orderings.len() { - *random_idx = 0; - } - - random_orderings[ridx] as usize - }; - - let mut random_idx_a = 0; - let mut random_idx_b = 0; - let mut random_idx_c = 0; - - let mut last_element_a = -1; - let mut last_element_b = -1; - - let mut rand_counter_b = 0; - let mut rand_counter_c = 0; - - let mut streak_counter_a = 0; - let mut streak_counter_b = 0; - - // Examples, a = 3, b = 5, c = 9. - // Correct Ord -> 10010 | is_less(a, b) is_less(a, a) is_less(b, a) is_less(a, c) is_less(c, a) - let mut invalid_ord_comp_functions: Vec<Box<dyn FnMut(&T, &T) -> Ordering>> = vec![ - Box::new(|_a, _b| -> Ordering { - // random - // Eg. is_less(3, 5) == true, is_less(3, 5) == false - - let idx = get_random_0_1_or_2(&mut random_idx_a); - [Ordering::Less, Ordering::Equal, Ordering::Greater][idx] - }), - Box::new(|_a, _b| -> Ordering { - // everything is less -> 11111 - Ordering::Less - }), - Box::new(|_a, _b| -> Ordering { - // everything is equal -> 00000 - Ordering::Equal - }), - Box::new(|_a, _b| -> Ordering { - // everything is greater -> 00000 - // Eg. is_less(3, 5) == false, is_less(5, 3) == false, is_less(3, 3) == false - Ordering::Greater - }), - Box::new(|a, b| -> Ordering { - // equal means less else greater -> 01000 - if a == b { Ordering::Less } else { Ordering::Greater } - }), - Box::new(|a, b| -> Ordering { - // Transitive breaker. remember last element -> 10001 - let lea = last_element_a; - let leb = last_element_b; - - let a_as_i32 = type_from_fn(a); - let b_as_i32 = type_from_fn(b); - - last_element_a = a_as_i32; - last_element_b = b_as_i32; - - if a_as_i32 == lea && b_as_i32 != leb { b.cmp(a) } else { a.cmp(b) } - }), - Box::new(|a, b| -> Ordering { - // Sampled random 1% of comparisons are reversed. - rand_counter_b += get_random_0_1_or_2(&mut random_idx_b); - if rand_counter_b >= 100 { - rand_counter_b = 0; - b.cmp(a) - } else { - a.cmp(b) - } - }), - Box::new(|a, b| -> Ordering { - // Sampled random 33% of comparisons are reversed. - rand_counter_c += get_random_0_1_or_2(&mut random_idx_c); - if rand_counter_c >= 3 { - rand_counter_c = 0; - b.cmp(a) - } else { - a.cmp(b) - } - }), - Box::new(|a, b| -> Ordering { - // STREAK_LEN comparisons yield a.cmp(b) then STREAK_LEN comparisons less. This can - // discover bugs that neither, random Ord, or just Less or Greater can find. Because it - // can push a pointer further than expected. Random Ord will average out how far a - // comparison based pointer travels. Just Less or Greater will be caught by pattern - // analysis and never enter interesting code. - const STREAK_LEN: usize = 50; - - streak_counter_a += 1; - if streak_counter_a <= STREAK_LEN { - a.cmp(b) - } else { - if streak_counter_a == STREAK_LEN * 2 { - streak_counter_a = 0; - } - Ordering::Less - } - }), - Box::new(|a, b| -> Ordering { - // See above. - const STREAK_LEN: usize = 50; - - streak_counter_b += 1; - if streak_counter_b <= STREAK_LEN { - a.cmp(b) - } else { - if streak_counter_b == STREAK_LEN * 2 { - streak_counter_b = 0; - } - Ordering::Greater - } - }), - ]; - - for comp_func in &mut invalid_ord_comp_functions { - let mut test_data: Vec<T> = pattern_fn(len).into_iter().map(type_into_fn).collect(); - let sum_before: i64 = test_data.iter().map(|x| type_from_fn(x) as i64).sum(); - - // It's ok to panic on Ord violation or to complete. - // In both cases the original elements must still be present. - let _ = panic::catch_unwind(AssertUnwindSafe(|| { - <S as Sort>::sort_by(&mut test_data, &mut *comp_func); - })); - - // If the sum before and after don't match, it means the set of elements hasn't remained the - // same. - let sum_after: i64 = test_data.iter().map(|x| type_from_fn(x) as i64).sum(); - assert_eq!(sum_before, sum_after); - - if cfg!(miri) { - // This test is prohibitively expensive in miri, so only run one of the comparison - // functions. This test is not expected to yield direct UB, but rather surface potential - // UB by showing that the sum is different now. - break; - } - } -} - -gen_sort_test_fns_with_default_patterns_3_ty!( - violate_ord_retain_orig_set, - violate_ord_retain_orig_set, - [] -); - -macro_rules! instantiate_sort_test_inner { - ($sort_impl:ty, miri_yes, $test_fn_name:ident) => { - #[test] - fn $test_fn_name() { - $crate::sort::tests::$test_fn_name::<$sort_impl>(); - } - }; - ($sort_impl:ty, miri_no, $test_fn_name:ident) => { - #[test] - #[cfg_attr(miri, ignore)] - fn $test_fn_name() { - $crate::sort::tests::$test_fn_name::<$sort_impl>(); - } - }; -} - -// Using this construct allows us to get warnings for unused test functions. -macro_rules! define_instantiate_sort_tests { - ($([$miri_use:ident, $test_fn_name:ident]),*,) => { - $(pub fn $test_fn_name<S: Sort>() { - ${concat($test_fn_name, _impl)}::<S>(); - })* - - - macro_rules! instantiate_sort_tests_gen { - ($sort_impl:ty) => { - $( - instantiate_sort_test_inner!( - $sort_impl, - $miri_use, - $test_fn_name - ); - )* - } - } - }; -} - -// Some tests are not tested with miri to avoid prohibitively long test times. This leaves coverage -// holes, but the way they are selected should make for relatively small holes. Many properties that -// can lead to UB are tested directly, for example that the original set of elements is retained -// even when a panic occurs or Ord is implemented incorrectly. -define_instantiate_sort_tests!( - [miri_yes, basic], - [miri_yes, fixed_seed], - [miri_yes, fixed_seed_rand_vec_prefix], - [miri_yes, int_edge], - [miri_yes, sort_vs_sort_by], - [miri_yes, correct_i32_random], - [miri_yes, correct_i32_random_z1], - [miri_yes, correct_i32_random_d2], - [miri_yes, correct_i32_random_d20], - [miri_yes, correct_i32_random_s95], - [miri_yes, correct_i32_ascending], - [miri_yes, correct_i32_descending], - [miri_yes, correct_i32_saw_mixed], - [miri_no, correct_i32_random_d4], - [miri_no, correct_i32_random_d8], - [miri_no, correct_i32_random_d311], - [miri_no, correct_i32_random_d1024], - [miri_no, correct_i32_random_z1_03], - [miri_no, correct_i32_random_z2], - [miri_no, correct_i32_random_s50], - [miri_no, correct_i32_narrow], - [miri_no, correct_i32_all_equal], - [miri_no, correct_i32_saw_mixed_range], - [miri_yes, correct_i32_pipe_organ], - [miri_no, correct_u64_random], - [miri_yes, correct_u64_random_z1], - [miri_no, correct_u64_random_d2], - [miri_no, correct_u64_random_d20], - [miri_no, correct_u64_random_s95], - [miri_no, correct_u64_ascending], - [miri_no, correct_u64_descending], - [miri_no, correct_u64_saw_mixed], - [miri_no, correct_u128_random], - [miri_yes, correct_u128_random_z1], - [miri_no, correct_u128_random_d2], - [miri_no, correct_u128_random_d20], - [miri_no, correct_u128_random_s95], - [miri_no, correct_u128_ascending], - [miri_no, correct_u128_descending], - [miri_no, correct_u128_saw_mixed], - [miri_no, correct_cell_i32_random], - [miri_yes, correct_cell_i32_random_z1], - [miri_no, correct_cell_i32_random_d2], - [miri_no, correct_cell_i32_random_d20], - [miri_no, correct_cell_i32_random_s95], - [miri_no, correct_cell_i32_ascending], - [miri_no, correct_cell_i32_descending], - [miri_no, correct_cell_i32_saw_mixed], - [miri_no, correct_string_random], - [miri_yes, correct_string_random_z1], - [miri_no, correct_string_random_d2], - [miri_no, correct_string_random_d20], - [miri_no, correct_string_random_s95], - [miri_no, correct_string_ascending], - [miri_no, correct_string_descending], - [miri_no, correct_string_saw_mixed], - [miri_no, correct_f128_random], - [miri_yes, correct_f128_random_z1], - [miri_no, correct_f128_random_d2], - [miri_no, correct_f128_random_d20], - [miri_no, correct_f128_random_s95], - [miri_no, correct_f128_ascending], - [miri_no, correct_f128_descending], - [miri_no, correct_f128_saw_mixed], - [miri_no, correct_1k_random], - [miri_yes, correct_1k_random_z1], - [miri_no, correct_1k_random_d2], - [miri_no, correct_1k_random_d20], - [miri_no, correct_1k_random_s95], - [miri_no, correct_1k_ascending], - [miri_no, correct_1k_descending], - [miri_no, correct_1k_saw_mixed], - [miri_no, correct_dyn_val_random], - [miri_yes, correct_dyn_val_random_z1], - [miri_no, correct_dyn_val_random_d2], - [miri_no, correct_dyn_val_random_d20], - [miri_no, correct_dyn_val_random_s95], - [miri_no, correct_dyn_val_ascending], - [miri_no, correct_dyn_val_descending], - [miri_no, correct_dyn_val_saw_mixed], - [miri_no, stability_legacy], - [miri_no, stability_i32_random], - [miri_yes, stability_i32_random_z1], - [miri_no, stability_i32_random_d2], - [miri_no, stability_i32_random_d20], - [miri_no, stability_i32_random_s95], - [miri_no, stability_i32_ascending], - [miri_no, stability_i32_descending], - [miri_no, stability_i32_saw_mixed], - [miri_no, stability_cell_i32_random], - [miri_yes, stability_cell_i32_random_z1], - [miri_no, stability_cell_i32_random_d2], - [miri_no, stability_cell_i32_random_d20], - [miri_no, stability_cell_i32_random_s95], - [miri_no, stability_cell_i32_ascending], - [miri_no, stability_cell_i32_descending], - [miri_no, stability_cell_i32_saw_mixed], - [miri_no, stability_string_random], - [miri_yes, stability_string_random_z1], - [miri_no, stability_string_random_d2], - [miri_no, stability_string_random_d20], - [miri_no, stability_string_random_s95], - [miri_no, stability_string_ascending], - [miri_no, stability_string_descending], - [miri_no, stability_string_saw_mixed], - [miri_no, observable_is_less_random], - [miri_yes, observable_is_less_random_z1], - [miri_no, observable_is_less_random_d2], - [miri_no, observable_is_less_random_d20], - [miri_no, observable_is_less_random_s95], - [miri_no, observable_is_less_ascending], - [miri_no, observable_is_less_descending], - [miri_no, observable_is_less_saw_mixed], - [miri_no, panic_retain_orig_set_i32_random], - [miri_yes, panic_retain_orig_set_i32_random_z1], - [miri_no, panic_retain_orig_set_i32_random_d2], - [miri_no, panic_retain_orig_set_i32_random_d20], - [miri_no, panic_retain_orig_set_i32_random_s95], - [miri_no, panic_retain_orig_set_i32_ascending], - [miri_no, panic_retain_orig_set_i32_descending], - [miri_no, panic_retain_orig_set_i32_saw_mixed], - [miri_no, panic_retain_orig_set_cell_i32_random], - [miri_yes, panic_retain_orig_set_cell_i32_random_z1], - [miri_no, panic_retain_orig_set_cell_i32_random_d2], - [miri_no, panic_retain_orig_set_cell_i32_random_d20], - [miri_no, panic_retain_orig_set_cell_i32_random_s95], - [miri_no, panic_retain_orig_set_cell_i32_ascending], - [miri_no, panic_retain_orig_set_cell_i32_descending], - [miri_no, panic_retain_orig_set_cell_i32_saw_mixed], - [miri_no, panic_retain_orig_set_string_random], - [miri_yes, panic_retain_orig_set_string_random_z1], - [miri_no, panic_retain_orig_set_string_random_d2], - [miri_no, panic_retain_orig_set_string_random_d20], - [miri_no, panic_retain_orig_set_string_random_s95], - [miri_no, panic_retain_orig_set_string_ascending], - [miri_no, panic_retain_orig_set_string_descending], - [miri_no, panic_retain_orig_set_string_saw_mixed], - [miri_no, panic_observable_is_less_random], - [miri_yes, panic_observable_is_less_random_z1], - [miri_no, panic_observable_is_less_random_d2], - [miri_no, panic_observable_is_less_random_d20], - [miri_no, panic_observable_is_less_random_s95], - [miri_no, panic_observable_is_less_ascending], - [miri_no, panic_observable_is_less_descending], - [miri_no, panic_observable_is_less_saw_mixed], - [miri_no, deterministic_i32_random], - [miri_yes, deterministic_i32_random_z1], - [miri_no, deterministic_i32_random_d2], - [miri_no, deterministic_i32_random_d20], - [miri_no, deterministic_i32_random_s95], - [miri_no, deterministic_i32_ascending], - [miri_no, deterministic_i32_descending], - [miri_no, deterministic_i32_saw_mixed], - [miri_no, deterministic_cell_i32_random], - [miri_yes, deterministic_cell_i32_random_z1], - [miri_no, deterministic_cell_i32_random_d2], - [miri_no, deterministic_cell_i32_random_d20], - [miri_no, deterministic_cell_i32_random_s95], - [miri_no, deterministic_cell_i32_ascending], - [miri_no, deterministic_cell_i32_descending], - [miri_no, deterministic_cell_i32_saw_mixed], - [miri_no, deterministic_string_random], - [miri_yes, deterministic_string_random_z1], - [miri_no, deterministic_string_random_d2], - [miri_no, deterministic_string_random_d20], - [miri_no, deterministic_string_random_s95], - [miri_no, deterministic_string_ascending], - [miri_no, deterministic_string_descending], - [miri_no, deterministic_string_saw_mixed], - [miri_no, self_cmp_i32_random], - [miri_yes, self_cmp_i32_random_z1], - [miri_no, self_cmp_i32_random_d2], - [miri_no, self_cmp_i32_random_d20], - [miri_no, self_cmp_i32_random_s95], - [miri_no, self_cmp_i32_ascending], - [miri_no, self_cmp_i32_descending], - [miri_no, self_cmp_i32_saw_mixed], - [miri_no, self_cmp_cell_i32_random], - [miri_yes, self_cmp_cell_i32_random_z1], - [miri_no, self_cmp_cell_i32_random_d2], - [miri_no, self_cmp_cell_i32_random_d20], - [miri_no, self_cmp_cell_i32_random_s95], - [miri_no, self_cmp_cell_i32_ascending], - [miri_no, self_cmp_cell_i32_descending], - [miri_no, self_cmp_cell_i32_saw_mixed], - [miri_no, self_cmp_string_random], - [miri_yes, self_cmp_string_random_z1], - [miri_no, self_cmp_string_random_d2], - [miri_no, self_cmp_string_random_d20], - [miri_no, self_cmp_string_random_s95], - [miri_no, self_cmp_string_ascending], - [miri_no, self_cmp_string_descending], - [miri_no, self_cmp_string_saw_mixed], - [miri_no, violate_ord_retain_orig_set_i32_random], - [miri_yes, violate_ord_retain_orig_set_i32_random_z1], - [miri_no, violate_ord_retain_orig_set_i32_random_d2], - [miri_no, violate_ord_retain_orig_set_i32_random_d20], - [miri_no, violate_ord_retain_orig_set_i32_random_s95], - [miri_no, violate_ord_retain_orig_set_i32_ascending], - [miri_no, violate_ord_retain_orig_set_i32_descending], - [miri_no, violate_ord_retain_orig_set_i32_saw_mixed], - [miri_no, violate_ord_retain_orig_set_cell_i32_random], - [miri_yes, violate_ord_retain_orig_set_cell_i32_random_z1], - [miri_no, violate_ord_retain_orig_set_cell_i32_random_d2], - [miri_no, violate_ord_retain_orig_set_cell_i32_random_d20], - [miri_no, violate_ord_retain_orig_set_cell_i32_random_s95], - [miri_no, violate_ord_retain_orig_set_cell_i32_ascending], - [miri_no, violate_ord_retain_orig_set_cell_i32_descending], - [miri_no, violate_ord_retain_orig_set_cell_i32_saw_mixed], - [miri_no, violate_ord_retain_orig_set_string_random], - [miri_yes, violate_ord_retain_orig_set_string_random_z1], - [miri_no, violate_ord_retain_orig_set_string_random_d2], - [miri_no, violate_ord_retain_orig_set_string_random_d20], - [miri_no, violate_ord_retain_orig_set_string_random_s95], - [miri_no, violate_ord_retain_orig_set_string_ascending], - [miri_no, violate_ord_retain_orig_set_string_descending], - [miri_no, violate_ord_retain_orig_set_string_saw_mixed], -); - -macro_rules! instantiate_sort_tests { - ($sort_impl:ty) => { - instantiate_sort_tests_gen!($sort_impl); - }; -} - -mod unstable { - struct SortImpl {} - - impl crate::sort::Sort for SortImpl { - fn name() -> String { - "rust_std_unstable".into() - } - - fn sort<T>(v: &mut [T]) - where - T: Ord, - { - v.sort_unstable(); - } - - fn sort_by<T, F>(v: &mut [T], mut compare: F) - where - F: FnMut(&T, &T) -> std::cmp::Ordering, - { - v.sort_unstable_by(|a, b| compare(a, b)); - } - } - - instantiate_sort_tests!(SortImpl); -} - -mod stable { - struct SortImpl {} - - impl crate::sort::Sort for SortImpl { - fn name() -> String { - "rust_std_stable".into() - } - - fn sort<T>(v: &mut [T]) - where - T: Ord, - { - v.sort(); - } - - fn sort_by<T, F>(v: &mut [T], mut compare: F) - where - F: FnMut(&T, &T) -> std::cmp::Ordering, - { - v.sort_by(|a, b| compare(a, b)); - } - } - - instantiate_sort_tests!(SortImpl); -} diff --git a/library/alloc/tests/sort/zipf.rs b/library/alloc/tests/sort/zipf.rs deleted file mode 100644 index 3dad2db521f..00000000000 --- a/library/alloc/tests/sort/zipf.rs +++ /dev/null @@ -1,208 +0,0 @@ -// This module implements a Zipfian distribution generator. -// -// Based on https://github.com/jonhoo/rust-zipf. - -use rand::Rng; - -/// Random number generator that generates Zipf-distributed random numbers using rejection -/// inversion. -#[derive(Clone, Copy)] -pub struct ZipfDistribution { - /// Number of elements - num_elements: f64, - /// Exponent parameter of the distribution - exponent: f64, - /// `hIntegral(1.5) - 1}` - h_integral_x1: f64, - /// `hIntegral(num_elements + 0.5)}` - h_integral_num_elements: f64, - /// `2 - hIntegralInverse(hIntegral(2.5) - h(2)}` - s: f64, -} - -impl ZipfDistribution { - /// Creates a new [Zipf-distributed](https://en.wikipedia.org/wiki/Zipf's_law) - /// random number generator. - /// - /// Note that both the number of elements and the exponent must be greater than 0. - pub fn new(num_elements: usize, exponent: f64) -> Result<Self, ()> { - if num_elements == 0 { - return Err(()); - } - if exponent <= 0f64 { - return Err(()); - } - - let z = ZipfDistribution { - num_elements: num_elements as f64, - exponent, - h_integral_x1: ZipfDistribution::h_integral(1.5, exponent) - 1f64, - h_integral_num_elements: ZipfDistribution::h_integral( - num_elements as f64 + 0.5, - exponent, - ), - s: 2f64 - - ZipfDistribution::h_integral_inv( - ZipfDistribution::h_integral(2.5, exponent) - - ZipfDistribution::h(2f64, exponent), - exponent, - ), - }; - - // populate cache - - Ok(z) - } -} - -impl ZipfDistribution { - fn next<R: Rng + ?Sized>(&self, rng: &mut R) -> usize { - // The paper describes an algorithm for exponents larger than 1 (Algorithm ZRI). - // - // The original method uses - // H(x) = (v + x)^(1 - q) / (1 - q) - // as the integral of the hat function. - // - // This function is undefined for q = 1, which is the reason for the limitation of the - // exponent. - // - // If instead the integral function - // H(x) = ((v + x)^(1 - q) - 1) / (1 - q) - // is used, for which a meaningful limit exists for q = 1, the method works for all - // positive exponents. - // - // The following implementation uses v = 0 and generates integral number in the range [1, - // num_elements]. This is different to the original method where v is defined to - // be positive and numbers are taken from [0, i_max]. This explains why the implementation - // looks slightly different. - - let hnum = self.h_integral_num_elements; - - loop { - use std::cmp; - let u: f64 = hnum + rng.random::<f64>() * (self.h_integral_x1 - hnum); - // u is uniformly distributed in (h_integral_x1, h_integral_num_elements] - - let x: f64 = ZipfDistribution::h_integral_inv(u, self.exponent); - - // Limit k to the range [1, num_elements] if it would be outside - // due to numerical inaccuracies. - let k64 = x.max(1.0).min(self.num_elements); - // float -> integer rounds towards zero, so we add 0.5 - // to prevent bias towards k == 1 - let k = cmp::max(1, (k64 + 0.5) as usize); - - // Here, the distribution of k is given by: - // - // P(k = 1) = C * (hIntegral(1.5) - h_integral_x1) = C - // P(k = m) = C * (hIntegral(m + 1/2) - hIntegral(m - 1/2)) for m >= 2 - // - // where C = 1 / (h_integral_num_elements - h_integral_x1) - if k64 - x <= self.s - || u >= ZipfDistribution::h_integral(k64 + 0.5, self.exponent) - - ZipfDistribution::h(k64, self.exponent) - { - // Case k = 1: - // - // The right inequality is always true, because replacing k by 1 gives - // u >= hIntegral(1.5) - h(1) = h_integral_x1 and u is taken from - // (h_integral_x1, h_integral_num_elements]. - // - // Therefore, the acceptance rate for k = 1 is P(accepted | k = 1) = 1 - // and the probability that 1 is returned as random value is - // P(k = 1 and accepted) = P(accepted | k = 1) * P(k = 1) = C = C / 1^exponent - // - // Case k >= 2: - // - // The left inequality (k - x <= s) is just a short cut - // to avoid the more expensive evaluation of the right inequality - // (u >= hIntegral(k + 0.5) - h(k)) in many cases. - // - // If the left inequality is true, the right inequality is also true: - // Theorem 2 in the paper is valid for all positive exponents, because - // the requirements h'(x) = -exponent/x^(exponent + 1) < 0 and - // (-1/hInverse'(x))'' = (1+1/exponent) * x^(1/exponent-1) >= 0 - // are both fulfilled. - // Therefore, f(x) = x - hIntegralInverse(hIntegral(x + 0.5) - h(x)) - // is a non-decreasing function. If k - x <= s holds, - // k - x <= s + f(k) - f(2) is obviously also true which is equivalent to - // -x <= -hIntegralInverse(hIntegral(k + 0.5) - h(k)), - // -hIntegralInverse(u) <= -hIntegralInverse(hIntegral(k + 0.5) - h(k)), - // and finally u >= hIntegral(k + 0.5) - h(k). - // - // Hence, the right inequality determines the acceptance rate: - // P(accepted | k = m) = h(m) / (hIntegrated(m+1/2) - hIntegrated(m-1/2)) - // The probability that m is returned is given by - // P(k = m and accepted) = P(accepted | k = m) * P(k = m) - // = C * h(m) = C / m^exponent. - // - // In both cases the probabilities are proportional to the probability mass - // function of the Zipf distribution. - - return k; - } - } - } -} - -impl rand::distr::Distribution<usize> for ZipfDistribution { - fn sample<R: Rng + ?Sized>(&self, rng: &mut R) -> usize { - self.next(rng) - } -} - -use std::fmt; -impl fmt::Debug for ZipfDistribution { - fn fmt(&self, f: &mut fmt::Formatter<'_>) -> Result<(), fmt::Error> { - f.debug_struct("ZipfDistribution") - .field("e", &self.exponent) - .field("n", &self.num_elements) - .finish() - } -} - -impl ZipfDistribution { - /// Computes `H(x)`, defined as - /// - /// - `(x^(1 - exponent) - 1) / (1 - exponent)`, if `exponent != 1` - /// - `log(x)`, if `exponent == 1` - /// - /// `H(x)` is an integral function of `h(x)`, the derivative of `H(x)` is `h(x)`. - fn h_integral(x: f64, exponent: f64) -> f64 { - let log_x = x.ln(); - helper2((1f64 - exponent) * log_x) * log_x - } - - /// Computes `h(x) = 1 / x^exponent` - fn h(x: f64, exponent: f64) -> f64 { - (-exponent * x.ln()).exp() - } - - /// The inverse function of `H(x)`. - /// Returns the `y` for which `H(y) = x`. - fn h_integral_inv(x: f64, exponent: f64) -> f64 { - let mut t: f64 = x * (1f64 - exponent); - if t < -1f64 { - // Limit value to the range [-1, +inf). - // t could be smaller than -1 in some rare cases due to numerical errors. - t = -1f64; - } - (helper1(t) * x).exp() - } -} - -/// Helper function that calculates `log(1 + x) / x`. -/// A Taylor series expansion is used, if x is close to 0. -fn helper1(x: f64) -> f64 { - if x.abs() > 1e-8 { x.ln_1p() / x } else { 1f64 - x * (0.5 - x * (1.0 / 3.0 - 0.25 * x)) } -} - -/// Helper function to calculate `(exp(x) - 1) / x`. -/// A Taylor series expansion is used, if x is close to 0. -fn helper2(x: f64) -> f64 { - if x.abs() > 1e-8 { - x.exp_m1() / x - } else { - 1f64 + x * 0.5 * (1f64 + x * 1.0 / 3.0 * (1f64 + 0.25 * x)) - } -} diff --git a/library/alloc/tests/str.rs b/library/alloc/tests/str.rs deleted file mode 100644 index 906fa2d425e..00000000000 --- a/library/alloc/tests/str.rs +++ /dev/null @@ -1,2461 +0,0 @@ -#![allow(invalid_from_utf8)] - -use std::assert_matches::assert_matches; -use std::borrow::Cow; -use std::char::MAX_LEN_UTF8; -use std::cmp::Ordering::{Equal, Greater, Less}; -use std::str::{from_utf8, from_utf8_unchecked}; - -#[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] -fn test_join_issue_80335() { - use core::borrow::Borrow; - use core::cell::Cell; - - struct WeirdBorrow { - state: Cell<bool>, - } - - impl Default for WeirdBorrow { - fn default() -> Self { - WeirdBorrow { state: Cell::new(false) } - } - } - - impl Borrow<str> for WeirdBorrow { - fn borrow(&self) -> &str { - let state = self.state.get(); - if state { - "0" - } else { - self.state.set(true); - "123456" - } - } - } - - let arr: [WeirdBorrow; 3] = Default::default(); - test_join!("0-0-0", arr, "-"); -} - -#[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() { - let _ = &"中华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 rangeinclusive_len { - data: "abcdef"; - good: data[0..=5] == "abcdef"; - bad: data[0..=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 rangeinclusive_exhausted { - data: "abcdef"; - - good: data[0..=5] == "abcdef"; - good: data[{ - let mut iter = 0..=5; - iter.by_ref().count(); // exhaust it - iter - }] == ""; - - // 0..=6 is out of bounds before exhaustion, so it - // stands to reason that it still would be after. - bad: data[{ - let mut iter = 0..=6; - iter.by_ref().count(); // exhaust it - iter - }]; - 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() { - let _ = &LOREM_PARAGRAPH[..1024]; - } - // check the truncation in the panic message - #[test] - #[should_panic(expected = "luctus, im`[...]")] - fn test_slice_fail_truncated_2() { - let _ = &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αβγ"; - let _ = &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; - let _ = &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 test_const_is_utf8() { - const _: () = { - // 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 const_from_utf8_mostly_ascii() { - const _: () = { - // deny invalid bytes embedded in long stretches of ascii - let mut i = 32; - while i < 64 { - let mut data = [0; 128]; - data[i] = 0xC0; - assert!(from_utf8(&data).is_err()); - data[i] = 0xC2; - assert!(from_utf8(&data).is_err()); - - i = i + 1; - } - }; -} - -#[test] -fn from_utf8_error() { - macro_rules! test { - ($input: expr, $expected_valid_up_to:pat, $expected_error_len:pat) => { - let error = from_utf8($input).unwrap_err(); - assert_matches!(error.valid_up_to(), $expected_valid_up_to); - assert_matches!(error.error_len(), $expected_error_len); - - const _: () = { - match from_utf8($input) { - Err(error) => { - let valid_up_to = error.valid_up_to(); - let error_len = error.error_len(); - - assert!(matches!(valid_up_to, $expected_valid_up_to)); - assert!(matches!(error_len, $expected_error_len)); - } - Ok(_) => unreachable!(), - } - }; - }; - } - 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.add(0), b'h'); - assert_eq!(*buf.add(1), b'e'); - assert_eq!(*buf.add(2), b'l'); - assert_eq!(*buf.add(3), b'l'); - assert_eq!(*buf.add(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"; - let _ = 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!("\0\r\n\t".escape_debug().to_string(), "\\0\\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_iterator_advance() { - let s = "「赤錆」と呼ばれる鉄錆は、水の存在下での鉄の自然酸化によって生じる、オキシ水酸化鉄(III) 等の(含水)酸化物粒子の疎な凝集膜であるとみなせる。"; - let chars: Vec<char> = s.chars().collect(); - let mut it = s.chars(); - it.advance_by(1).unwrap(); - assert_eq!(it.next(), Some(chars[1])); - it.advance_by(33).unwrap(); - assert_eq!(it.next(), Some(chars[35])); -} - -#[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] -fn test_to_lowercase_rev_iterator() { - let s = "AÖßÜ💩ΣΤΙΓΜΑΣDžfiİ"; - let v = ['\u{307}', 'i', 'fi', 'dž', 'σ', 'α', 'μ', 'γ', 'ι', 'τ', 'σ', '💩', 'ü', 'ß', 'ö', 'a']; - - let mut pos = 0; - let it = s.chars().flat_map(|c| c.to_lowercase()).rev(); - - for c in it { - assert_eq!(c, v[pos]); - pos += 1; - } - assert_eq!(pos, v.len()); -} - -#[test] -fn test_to_uppercase_rev_iterator() { - let s = "aößü💩στιγμαςDžfiᾀ"; - let v = - ['Ι', 'Ἀ', 'I', 'F', 'DŽ', 'Σ', 'Α', 'Μ', 'Γ', 'Ι', 'Τ', 'Σ', '💩', 'Ü', 'S', 'S', 'Ö', 'A']; - - let mut pos = 0; - let it = s.chars().flat_map(|c| c.to_uppercase()).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; MAX_LEN_UTF8]; - 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; MAX_LEN_UTF8]; - 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_once() { - assert_eq!("".split_once("->"), None); - assert_eq!("-".split_once("->"), None); - assert_eq!("->".split_once("->"), Some(("", ""))); - assert_eq!("a->".split_once("->"), Some(("a", ""))); - assert_eq!("->b".split_once("->"), Some(("", "b"))); - assert_eq!("a->b".split_once("->"), Some(("a", "b"))); - assert_eq!("a->b->c".split_once("->"), Some(("a", "b->c"))); - assert_eq!("---".split_once("--"), Some(("", "-"))); -} - -#[test] -fn test_rsplit_once() { - assert_eq!("".rsplit_once("->"), None); - assert_eq!("-".rsplit_once("->"), None); - assert_eq!("->".rsplit_once("->"), Some(("", ""))); - assert_eq!("a->".rsplit_once("->"), Some(("a", ""))); - assert_eq!("->b".rsplit_once("->"), Some(("", "b"))); - assert_eq!("a->b".rsplit_once("->"), Some(("a", "b"))); - assert_eq!("a->b->c".rsplit_once("->"), Some(("a->b", "c"))); - assert_eq!("---".rsplit_once("--"), Some(("-", ""))); -} - -#[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() { - fn t(data: &str, expected: &[&str]) { - let lines: Vec<&str> = data.lines().collect(); - assert_eq!(lines, expected); - } - t("", &[]); - t("\n", &[""]); - t("\n2nd", &["", "2nd"]); - t("\r\n", &[""]); - t("bare\r", &["bare\r"]); - t("bare\rcr", &["bare\rcr"]); - t("Text\n\r", &["Text", "\r"]); - t( - "\nMäry häd ä little lämb\n\r\nLittle lämb\n", - &["", "Märy häd ä little lämb", "", "Little lämb"], - ); - t( - "\r\nMäry häd ä little lämb\n\nLittle lämb", - &["", "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(haystack: &str) { - let mut modified_needle = String::new(); - - for i in 0..haystack.len() { - // check different haystack lengths since we special-case short haystacks. - let haystack = &haystack[0..i]; - assert!(haystack.contains("")); - for j in 0..haystack.len() { - for k in j + 1..=haystack.len() { - let needle = &haystack[j..k]; - assert!(haystack.contains(needle)); - modified_needle.clear(); - modified_needle.push_str(needle); - modified_needle.replace_range(0..1, "\0"); - assert!(!haystack.contains(&modified_needle)); - - modified_needle.clear(); - modified_needle.push_str(needle); - modified_needle.replace_range(needle.len() - 1..needle.len(), "\0"); - assert!(!haystack.contains(&modified_needle)); - } - } - } -} - -#[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] -fn strslice_issue_104726() { - // Edge-case in the simd_contains impl. - // The first and last byte are the same so it backtracks by one byte - // which aligns with the end of the string. Previously incorrect offset calculations - // lead to out-of-bounds slicing. - #[rustfmt::skip] - let needle = "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaba"; - let haystack = "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaab"; - assert!(!haystack.contains(needle)); -} - -#[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 test_utf16_size_hint() { - assert_eq!("".encode_utf16().size_hint(), (0, Some(0))); - assert_eq!("123".encode_utf16().size_hint(), (1, Some(3))); - assert_eq!("1234".encode_utf16().size_hint(), (2, Some(4))); - assert_eq!("12345678".encode_utf16().size_hint(), (3, Some(8))); - - fn hint_vec(src: &str) -> Vec<(usize, Option<usize>)> { - let mut it = src.encode_utf16(); - let mut result = Vec::new(); - result.push(it.size_hint()); - while it.next().is_some() { - result.push(it.size_hint()) - } - result - } - - assert_eq!(hint_vec("12"), [(1, Some(2)), (1, Some(1)), (0, Some(0))]); - assert_eq!(hint_vec("\u{101234}"), [(2, Some(4)), (1, Some(1)), (0, Some(0))]); - assert_eq!(hint_vec("\u{101234}a"), [(2, Some(5)), (2, Some(2)), (1, Some(1)), (0, Some(0))]); -} - -#[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(), "ασ''α"); - - // https://github.com/rust-lang/rust/issues/124714 - // input lengths around the boundary of the chunk size used by the ascii prefix optimization - assert_eq!("abcdefghijklmnoΣ".to_lowercase(), "abcdefghijklmnoς"); - assert_eq!("abcdefghijklmnopΣ".to_lowercase(), "abcdefghijklmnopς"); - assert_eq!("abcdefghijklmnopqΣ".to_lowercase(), "abcdefghijklmnopqς"); - - // a really long string that has it's lowercase form - // even longer. this tests that implementations don't assume - // an incorrect upper bound on allocations - let upper = str::repeat("İ", 512); - let lower = str::repeat("i̇", 512); - assert_eq!(upper.to_lowercase(), lower); - - // a really long ascii-only string. - // This test that the ascii hot-path - // functions correctly - let upper = str::repeat("A", 511); - let lower = str::repeat("a", 511); - assert_eq!(upper.to_lowercase(), lower); -} - -#[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<P>(rev: bool, pat: P, haystack: &str, right: Vec<SearchStep>) - where - P: for<'a> Pattern<Searcher<'a>: ReverseSearcher<'a>>, - { - 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),] - ); - - // See #85462 - #[test] - fn str_searcher_empty_needle_after_done() { - // Empty needle and haystack - { - let mut searcher = "".into_searcher(""); - - assert_eq!(searcher.next(), SearchStep::Match(0, 0)); - assert_eq!(searcher.next(), SearchStep::Done); - assert_eq!(searcher.next(), SearchStep::Done); - assert_eq!(searcher.next(), SearchStep::Done); - - let mut searcher = "".into_searcher(""); - - assert_eq!(searcher.next_back(), SearchStep::Match(0, 0)); - assert_eq!(searcher.next_back(), SearchStep::Done); - assert_eq!(searcher.next_back(), SearchStep::Done); - assert_eq!(searcher.next_back(), SearchStep::Done); - } - // Empty needle and non-empty haystack - { - let mut searcher = "".into_searcher("a"); - - assert_eq!(searcher.next(), SearchStep::Match(0, 0)); - assert_eq!(searcher.next(), SearchStep::Reject(0, 1)); - assert_eq!(searcher.next(), SearchStep::Match(1, 1)); - assert_eq!(searcher.next(), SearchStep::Done); - assert_eq!(searcher.next(), SearchStep::Done); - assert_eq!(searcher.next(), SearchStep::Done); - - let mut searcher = "".into_searcher("a"); - - assert_eq!(searcher.next_back(), SearchStep::Match(1, 1)); - assert_eq!(searcher.next_back(), SearchStep::Reject(0, 1)); - assert_eq!(searcher.next_back(), SearchStep::Match(0, 0)); - assert_eq!(searcher.next_back(), SearchStep::Done); - assert_eq!(searcher.next_back(), SearchStep::Done); - assert_eq!(searcher.next_back(), SearchStep::Done); - } - } -} - -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<P>(p: P) - where - for<'b> &'b P: Pattern, - { - for _ in 0..3 { - "asdf".find(&p); - } - } - - foo::<&str>("x"); -} - -#[test] -fn test_str_multiline() { - let a: String = "this \ -is a test" - .to_string(); - let b: String = "this \ - is \ - another \ - test" - .to_string(); - assert_eq!(a, "this is a test".to_string()); - assert_eq!(b, "this is another test".to_string()); -} - -#[test] -fn test_str_escapes() { - let x = "\\\\\ - "; - assert_eq!(x, r"\\"); // extraneous whitespace stripped -} - -#[test] -fn const_str_ptr() { - const A: [u8; 2] = ['h' as u8, 'i' as u8]; - const B: &'static [u8; 2] = &A; - const C: *const u8 = B as *const u8; - - // Miri does not deduplicate consts (https://github.com/rust-lang/miri/issues/131) - #[cfg(not(miri))] - { - let foo = &A as *const u8; - assert_eq!(foo, C); - } - - unsafe { - assert_eq!(from_utf8_unchecked(&A), "hi"); - assert_eq!(*C, A[0]); - assert_eq!(*(&B[0] as *const u8), A[0]); - } -} - -#[test] -fn utf8() { - let yen: char = '¥'; // 0xa5 - let c_cedilla: char = 'ç'; // 0xe7 - let thorn: char = 'þ'; // 0xfe - let y_diaeresis: char = 'ÿ'; // 0xff - let pi: char = 'Π'; // 0x3a0 - - assert_eq!(yen as isize, 0xa5); - assert_eq!(c_cedilla as isize, 0xe7); - assert_eq!(thorn as isize, 0xfe); - assert_eq!(y_diaeresis as isize, 0xff); - assert_eq!(pi as isize, 0x3a0); - - assert_eq!(pi as isize, '\u{3a0}' as isize); - assert_eq!('\x0a' as isize, '\n' as isize); - - let bhutan: String = "འབྲུག་ཡུལ།".to_string(); - let japan: String = "日本".to_string(); - let uzbekistan: String = "Ўзбекистон".to_string(); - let austria: String = "Österreich".to_string(); - - let bhutan_e: String = - "\u{f60}\u{f56}\u{fb2}\u{f74}\u{f42}\u{f0b}\u{f61}\u{f74}\u{f63}\u{f0d}".to_string(); - let japan_e: String = "\u{65e5}\u{672c}".to_string(); - let uzbekistan_e: String = - "\u{40e}\u{437}\u{431}\u{435}\u{43a}\u{438}\u{441}\u{442}\u{43e}\u{43d}".to_string(); - let austria_e: String = "\u{d6}sterreich".to_string(); - - let oo: char = 'Ö'; - assert_eq!(oo as isize, 0xd6); - - fn check_str_eq(a: String, b: String) { - let mut i: isize = 0; - for ab in a.bytes() { - println!("{i}"); - println!("{ab}"); - let bb: u8 = b.as_bytes()[i as usize]; - println!("{bb}"); - assert_eq!(ab, bb); - i += 1; - } - } - - check_str_eq(bhutan, bhutan_e); - check_str_eq(japan, japan_e); - check_str_eq(uzbekistan, uzbekistan_e); - check_str_eq(austria, austria_e); -} - -#[test] -fn utf8_chars() { - // Chars of 1, 2, 3, and 4 bytes - let chs: Vec<char> = vec!['e', 'é', '€', '\u{10000}']; - let s: String = chs.iter().cloned().collect(); - let schs: Vec<char> = s.chars().collect(); - - assert_eq!(s.len(), 10); - assert_eq!(s.chars().count(), 4); - assert_eq!(schs.len(), 4); - assert_eq!(schs.iter().cloned().collect::<String>(), s); - - assert!(from_utf8(s.as_bytes()).is_ok()); - // invalid prefix - assert!(!from_utf8(&[0x80]).is_ok()); - // invalid 2 byte prefix - assert!(!from_utf8(&[0xc0]).is_ok()); - assert!(!from_utf8(&[0xc0, 0x10]).is_ok()); - // invalid 3 byte prefix - assert!(!from_utf8(&[0xe0]).is_ok()); - assert!(!from_utf8(&[0xe0, 0x10]).is_ok()); - assert!(!from_utf8(&[0xe0, 0xff, 0x10]).is_ok()); - // invalid 4 byte prefix - assert!(!from_utf8(&[0xf0]).is_ok()); - assert!(!from_utf8(&[0xf0, 0x10]).is_ok()); - assert!(!from_utf8(&[0xf0, 0xff, 0x10]).is_ok()); - assert!(!from_utf8(&[0xf0, 0xff, 0xff, 0x10]).is_ok()); -} - -#[test] -fn utf8_char_counts() { - let strs = [("e", 1), ("é", 1), ("€", 1), ("\u{10000}", 1), ("eé€\u{10000}", 4)]; - let spread = if cfg!(miri) { 4 } else { 8 }; - let mut reps = [8, 64, 256, 512] - .iter() - .copied() - .flat_map(|n| n - spread..=n + spread) - .collect::<Vec<usize>>(); - if cfg!(not(miri)) { - reps.extend([1024, 1 << 16].iter().copied().flat_map(|n| n - spread..=n + spread)); - } - let counts = if cfg!(miri) { 0..1 } else { 0..8 }; - let padding = counts.map(|len| " ".repeat(len)).collect::<Vec<String>>(); - - for repeat in reps { - for (tmpl_str, tmpl_char_count) in strs { - for pad_start in &padding { - for pad_end in &padding { - // Create a string with padding... - let with_padding = - format!("{}{}{}", pad_start, tmpl_str.repeat(repeat), pad_end); - // ...and then skip past that padding. This should ensure - // that we test several different alignments for both head - // and tail. - let si = pad_start.len(); - let ei = with_padding.len() - pad_end.len(); - let target = &with_padding[si..ei]; - - assert!(!target.starts_with(" ") && !target.ends_with(" ")); - let expected_count = tmpl_char_count * repeat; - assert_eq!( - expected_count, - target.chars().count(), - "wrong count for `{:?}.repeat({})` (padding: `{:?}`)", - tmpl_str, - repeat, - (pad_start.len(), pad_end.len()), - ); - } - } - } - } -} - -#[test] -fn floor_char_boundary() { - fn check_many(s: &str, arg: impl IntoIterator<Item = usize>, ret: usize) { - for idx in arg { - assert_eq!( - s.floor_char_boundary(idx), - ret, - "{:?}.floor_char_boundary({:?}) != {:?}", - s, - idx, - ret - ); - } - } - - // edge case - check_many("", [0, 1, isize::MAX as usize, usize::MAX], 0); - - // basic check - check_many("x", [0], 0); - check_many("x", [1, isize::MAX as usize, usize::MAX], 1); - - // 1-byte chars - check_many("jp", [0], 0); - check_many("jp", [1], 1); - check_many("jp", 2..4, 2); - - // 2-byte chars - check_many("ĵƥ", 0..2, 0); - check_many("ĵƥ", 2..4, 2); - check_many("ĵƥ", 4..6, 4); - - // 3-byte chars - check_many("日本", 0..3, 0); - check_many("日本", 3..6, 3); - check_many("日本", 6..8, 6); - - // 4-byte chars - check_many("🇯🇵", 0..4, 0); - check_many("🇯🇵", 4..8, 4); - check_many("🇯🇵", 8..10, 8); -} - -#[test] -fn ceil_char_boundary() { - fn check_many(s: &str, arg: impl IntoIterator<Item = usize>, ret: usize) { - for idx in arg { - assert_eq!( - s.ceil_char_boundary(idx), - ret, - "{:?}.ceil_char_boundary({:?}) != {:?}", - s, - idx, - ret - ); - } - } - - // edge case - check_many("", [0], 0); - - // basic check - check_many("x", [0], 0); - check_many("x", [1], 1); - - // 1-byte chars - check_many("jp", [0], 0); - check_many("jp", [1], 1); - check_many("jp", [2], 2); - - // 2-byte chars - check_many("ĵƥ", 0..=0, 0); - check_many("ĵƥ", 1..=2, 2); - check_many("ĵƥ", 3..=4, 4); - - // 3-byte chars - check_many("日本", 0..=0, 0); - check_many("日本", 1..=3, 3); - check_many("日本", 4..=6, 6); - - // 4-byte chars - check_many("🇯🇵", 0..=0, 0); - check_many("🇯🇵", 1..=4, 4); - check_many("🇯🇵", 5..=8, 8); - - // above len - check_many("hello", 5..=10, 5); -} diff --git a/library/alloc/tests/string.rs b/library/alloc/tests/string.rs deleted file mode 100644 index d996c55f946..00000000000 --- a/library/alloc/tests/string.rs +++ /dev/null @@ -1,914 +0,0 @@ -use std::assert_matches::assert_matches; -use std::borrow::Cow; -use std::cell::Cell; -use std::collections::TryReserveErrorKind::*; -use std::ops::Bound::*; -use std::ops::{Bound, RangeBounds}; -use std::{panic, str}; - -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_fromutf8error_into_lossy() { - fn func(input: &[u8]) -> String { - String::from_utf8(input.to_owned()).unwrap_or_else(|e| e.into_utf8_lossy()) - } - - let xs = b"hello"; - let ys = "hello".to_owned(); - assert_eq!(func(xs), ys); - - let xs = "ศไทย中华Việt Nam".as_bytes(); - let ys = "ศไทย中华Việt Nam".to_owned(); - assert_eq!(func(xs), ys); - - let xs = b"Hello\xC2 There\xFF Goodbye"; - assert_eq!(func(xs), "Hello\u{FFFD} There\u{FFFD} Goodbye".to_owned()); - - let xs = b"Hello\xC0\x80 There\xE6\x83 Goodbye"; - assert_eq!(func(xs), "Hello\u{FFFD}\u{FFFD} There\u{FFFD} Goodbye".to_owned()); - - let xs = b"\xF5foo\xF5\x80bar"; - assert_eq!(func(xs), "\u{FFFD}foo\u{FFFD}\u{FFFD}bar".to_owned()); - - let xs = b"\xF1foo\xF1\x80bar\xF1\x80\x80baz"; - assert_eq!(func(xs), "\u{FFFD}foo\u{FFFD}bar\u{FFFD}baz".to_owned()); - - let xs = b"\xF4foo\xF4\x80bar\xF4\xBFbaz"; - assert_eq!(func(xs), "\u{FFFD}foo\u{FFFD}bar\u{FFFD}\u{FFFD}baz".to_owned()); - - let xs = b"\xF0\x80\x80\x80foo\xF0\x90\x80\x80bar"; - assert_eq!(func(xs), "\u{FFFD}\u{FFFD}\u{FFFD}\u{FFFD}foo\u{10000}bar".to_owned()); - - // surrogates - let xs = b"\xED\xA0\x80foo\xED\xBF\xBFbar"; - assert_eq!(func(xs), "\u{FFFD}\u{FFFD}\u{FFFD}foo\u{FFFD}\u{FFFD}\u{FFFD}bar".to_owned()); -} - -#[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 shan = String::from("山"); - let _broken_mountain = shan.split_off(1); -} - -#[test] -fn test_split_off_ascii() { - let mut ab = String::from("ABCD"); - let orig_capacity = ab.capacity(); - let cd = ab.split_off(2); - assert_eq!(ab, "AB"); - assert_eq!(cd, "CD"); - assert_eq!(ab.capacity(), orig_capacity); -} - -#[test] -fn test_split_off_unicode() { - let mut nihon = String::from("日本語"); - let orig_capacity = nihon.capacity(); - let go = nihon.split_off("日本".len()); - assert_eq!(nihon, "日本"); - assert_eq!(go, "語"); - assert_eq!(nihon.capacity(), orig_capacity); -} - -#[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_remove_matches() { - // test_single_pattern_occurrence - let mut s = "abc".to_string(); - s.remove_matches('b'); - assert_eq!(s, "ac"); - // repeat_test_single_pattern_occurrence - s.remove_matches('b'); - assert_eq!(s, "ac"); - - // test_single_character_pattern - let mut s = "abcb".to_string(); - s.remove_matches('b'); - assert_eq!(s, "ac"); - - // test_pattern_with_special_characters - let mut s = "ศไทย中华Việt Nam; foobarศ".to_string(); - s.remove_matches('ศ'); - assert_eq!(s, "ไทย中华Việt Nam; foobar"); - - // test_pattern_empty_text_and_pattern - let mut s = "".to_string(); - s.remove_matches(""); - assert_eq!(s, ""); - - // test_pattern_empty_text - let mut s = "".to_string(); - s.remove_matches("something"); - assert_eq!(s, ""); - - // test_empty_pattern - let mut s = "Testing with empty pattern.".to_string(); - s.remove_matches(""); - assert_eq!(s, "Testing with empty pattern."); - - // test_multiple_consecutive_patterns_1 - let mut s = "aaaaa".to_string(); - s.remove_matches('a'); - assert_eq!(s, ""); - - // test_multiple_consecutive_patterns_2 - let mut s = "Hello **world****today!**".to_string(); - s.remove_matches("**"); - assert_eq!(s, "Hello worldtoday!"); - - // test_case_insensitive_pattern - let mut s = "CASE ** SeNsItIvE ** PaTtErN.".to_string(); - s.remove_matches("sEnSiTiVe"); - assert_eq!(s, "CASE ** SeNsItIvE ** PaTtErN."); - - // test_pattern_with_digits - let mut s = "123 ** 456 ** 789".to_string(); - s.remove_matches("**"); - assert_eq!(s, "123 456 789"); - - // test_pattern_occurs_after_empty_string - let mut s = "abc X defXghi".to_string(); - s.remove_matches("X"); - assert_eq!(s, "abc defghi"); - - // test_large_pattern - let mut s = "aaaXbbbXcccXdddXeee".to_string(); - s.remove_matches("X"); - assert_eq!(s, "aaabbbcccdddeee"); - - // test_pattern_at_multiple_positions - let mut s = "Pattern ** found ** multiple ** times ** in ** text.".to_string(); - s.remove_matches("**"); - assert_eq!(s, "Pattern found multiple times in text."); -} - -#[test] -#[cfg_attr(not(panic = "unwind"), ignore = "test requires unwinding support")] -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, ""); - - let mut s = String::from("0è0"); - let _ = panic::catch_unwind(panic::AssertUnwindSafe(|| { - let mut count = 0; - s.retain(|_| { - count += 1; - match count { - 1 => false, - 2 => true, - _ => panic!(), - } - }); - })); - assert!(std::str::from_utf8(s.as_bytes()).is_ok()); -} - -#[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 = [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] -#[should_panic] -fn test_drain_start_overflow() { - let mut s = String::from("abc"); - s.drain((Excluded(usize::MAX), Included(0))); -} - -#[test] -#[should_panic] -fn test_drain_end_overflow() { - let mut s = String::from("abc"); - s.drain((Included(0), Included(usize::MAX))); -} - -#[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] -#[should_panic] -fn test_replace_range_start_overflow() { - let mut s = String::from("123"); - s.replace_range((Excluded(usize::MAX), Included(0)), ""); -} - -#[test] -#[should_panic] -fn test_replace_range_end_overflow() { - let mut s = String::from("456"); - s.replace_range((Included(0), Included(usize::MAX)), ""); -} - -#[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_replace_range_evil_start_bound() { - struct EvilRange(Cell<bool>); - - impl RangeBounds<usize> for EvilRange { - fn start_bound(&self) -> Bound<&usize> { - Bound::Included(if self.0.get() { - &1 - } else { - self.0.set(true); - &0 - }) - } - fn end_bound(&self) -> Bound<&usize> { - Bound::Unbounded - } - } - - let mut s = String::from("🦀"); - s.replace_range(EvilRange(Cell::new(false)), ""); - assert_eq!(Ok(""), str::from_utf8(s.as_bytes())); -} - -#[test] -fn test_replace_range_evil_end_bound() { - struct EvilRange(Cell<bool>); - - impl RangeBounds<usize> for EvilRange { - fn start_bound(&self) -> Bound<&usize> { - Bound::Included(&0) - } - fn end_bound(&self) -> Bound<&usize> { - Bound::Excluded(if self.0.get() { - &3 - } else { - self.0.set(true); - &4 - }) - } - } - - let mut s = String::from("🦀"); - s.replace_range(EvilRange(Cell::new(false)), ""); - assert_eq!(Ok(""), str::from_utf8(s.as_bytes())); -} - -#[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 -fn test_try_with_capacity() { - let string = String::try_with_capacity(1000).unwrap(); - assert_eq!(0, string.len()); - assert!(string.capacity() >= 1000 && string.capacity() <= isize::MAX as usize); - - assert!(String::try_with_capacity(usize::MAX).is_err()); -} - -#[test] -#[cfg_attr(miri, ignore)] // Miri does not support signalling OOM -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; - - { - // 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).map_err(|e| e.kind()) { - 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).map_err(|e| e.kind()) { - panic!("isize::MAX shouldn't trigger an overflow!"); - } - - // Check isize::MAX + 1 does count as overflow - assert_matches!( - empty_string.try_reserve(MAX_CAP + 1).map_err(|e| e.kind()), - Err(CapacityOverflow), - "isize::MAX + 1 should trigger an overflow!" - ); - - // Check usize::MAX does count as overflow - assert_matches!( - empty_string.try_reserve(MAX_USIZE).map_err(|e| e.kind()), - Err(CapacityOverflow), - "usize::MAX should trigger an overflow!" - ); - } - - { - // 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).map_err(|e| e.kind()) { - panic!("isize::MAX shouldn't trigger an overflow!"); - } - if let Err(CapacityOverflow) = ten_bytes.try_reserve(MAX_CAP - 10).map_err(|e| e.kind()) { - panic!("isize::MAX shouldn't trigger an overflow!"); - } - - assert_matches!( - ten_bytes.try_reserve(MAX_CAP - 9).map_err(|e| e.kind()), - Err(CapacityOverflow), - "isize::MAX + 1 should trigger an overflow!" - ); - - // Should always overflow in the add-to-len - assert_matches!( - ten_bytes.try_reserve(MAX_USIZE).map_err(|e| e.kind()), - Err(CapacityOverflow), - "usize::MAX should trigger an overflow!" - ); - } -} - -#[test] -#[cfg_attr(miri, ignore)] // Miri does not support signalling OOM -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 mut empty_string: String = String::new(); - - if let Err(CapacityOverflow) = empty_string.try_reserve_exact(MAX_CAP).map_err(|e| e.kind()) - { - panic!("isize::MAX shouldn't trigger an overflow!"); - } - if let Err(CapacityOverflow) = empty_string.try_reserve_exact(MAX_CAP).map_err(|e| e.kind()) - { - panic!("isize::MAX shouldn't trigger an overflow!"); - } - - assert_matches!( - empty_string.try_reserve_exact(MAX_CAP + 1).map_err(|e| e.kind()), - Err(CapacityOverflow), - "isize::MAX + 1 should trigger an overflow!" - ); - - assert_matches!( - empty_string.try_reserve_exact(MAX_USIZE).map_err(|e| e.kind()), - Err(CapacityOverflow), - "usize::MAX should trigger an overflow!" - ); - } - - { - let mut ten_bytes: String = String::from("0123456789"); - - if let Err(CapacityOverflow) = - ten_bytes.try_reserve_exact(MAX_CAP - 10).map_err(|e| e.kind()) - { - panic!("isize::MAX shouldn't trigger an overflow!"); - } - if let Err(CapacityOverflow) = - ten_bytes.try_reserve_exact(MAX_CAP - 10).map_err(|e| e.kind()) - { - panic!("isize::MAX shouldn't trigger an overflow!"); - } - - assert_matches!( - ten_bytes.try_reserve_exact(MAX_CAP - 9).map_err(|e| e.kind()), - Err(CapacityOverflow), - "isize::MAX + 1 should trigger an overflow!" - ); - - assert_matches!( - ten_bytes.try_reserve_exact(MAX_USIZE).map_err(|e| e.kind()), - Err(CapacityOverflow), - "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()); -} - -#[test] -fn test_str_concat() { - let a: String = "hello".to_string(); - let b: String = "world".to_string(); - let s: String = format!("{a}{b}"); - assert_eq!(s.as_bytes()[9], 'd' as u8); -} diff --git a/library/alloc/tests/sync.rs b/library/alloc/tests/sync.rs deleted file mode 100644 index 6d3ab1b1d11..00000000000 --- a/library/alloc/tests/sync.rs +++ /dev/null @@ -1,720 +0,0 @@ -use alloc::sync::*; -use std::alloc::{AllocError, Allocator, Layout}; -use std::any::Any; -use std::clone::Clone; -use std::mem::MaybeUninit; -use std::option::Option::None; -use std::ptr::NonNull; -use std::sync::Mutex; -use std::sync::atomic::Ordering::*; -use std::sync::atomic::{self, AtomicUsize}; -use std::sync::mpsc::channel; -use std::thread; - -struct Canary(*mut AtomicUsize); - -impl Drop for Canary { - fn drop(&mut self) { - unsafe { - match *self { - Canary(c) => { - (*c).fetch_add(1, SeqCst); - } - } - } - } -} - -struct AllocCanary<'a>(&'a AtomicUsize); - -impl<'a> AllocCanary<'a> { - fn new(counter: &'a AtomicUsize) -> Self { - counter.fetch_add(1, SeqCst); - Self(counter) - } -} - -unsafe impl Allocator for AllocCanary<'_> { - fn allocate(&self, layout: Layout) -> Result<NonNull<[u8]>, AllocError> { - std::alloc::Global.allocate(layout) - } - - unsafe fn deallocate(&self, ptr: NonNull<u8>, layout: Layout) { - unsafe { std::alloc::Global.deallocate(ptr, layout) } - } -} - -impl Clone for AllocCanary<'_> { - fn clone(&self) -> Self { - Self::new(self.0) - } -} - -impl Drop for AllocCanary<'_> { - fn drop(&mut self) { - self.0.fetch_sub(1, SeqCst); - } -} - -#[test] -#[cfg_attr(target_os = "emscripten", ignore)] -fn manually_share_arc() { - let v = vec![1, 2, 3, 4, 5, 6, 7, 8, 9, 10]; - let arc_v = Arc::new(v); - - let (tx, rx) = channel(); - - let _t = thread::spawn(move || { - let arc_v: Arc<Vec<i32>> = rx.recv().unwrap(); - assert_eq!((*arc_v)[3], 4); - }); - - tx.send(arc_v.clone()).unwrap(); - - assert_eq!((*arc_v)[2], 3); - assert_eq!((*arc_v)[4], 5); -} - -#[test] -fn test_arc_get_mut() { - let mut x = Arc::new(3); - *Arc::get_mut(&mut x).unwrap() = 4; - assert_eq!(*x, 4); - let y = x.clone(); - assert!(Arc::get_mut(&mut x).is_none()); - drop(y); - assert!(Arc::get_mut(&mut x).is_some()); - let _w = Arc::downgrade(&x); - assert!(Arc::get_mut(&mut x).is_none()); -} - -#[test] -fn weak_counts() { - assert_eq!(Weak::weak_count(&Weak::<u64>::new()), 0); - assert_eq!(Weak::strong_count(&Weak::<u64>::new()), 0); - - let a = Arc::new(0); - let w = Arc::downgrade(&a); - assert_eq!(Weak::strong_count(&w), 1); - assert_eq!(Weak::weak_count(&w), 1); - let w2 = w.clone(); - assert_eq!(Weak::strong_count(&w), 1); - assert_eq!(Weak::weak_count(&w), 2); - assert_eq!(Weak::strong_count(&w2), 1); - assert_eq!(Weak::weak_count(&w2), 2); - drop(w); - assert_eq!(Weak::strong_count(&w2), 1); - assert_eq!(Weak::weak_count(&w2), 1); - let a2 = a.clone(); - assert_eq!(Weak::strong_count(&w2), 2); - assert_eq!(Weak::weak_count(&w2), 1); - drop(a2); - drop(a); - assert_eq!(Weak::strong_count(&w2), 0); - assert_eq!(Weak::weak_count(&w2), 0); - drop(w2); -} - -#[test] -fn try_unwrap() { - let x = Arc::new(3); - assert_eq!(Arc::try_unwrap(x), Ok(3)); - let x = Arc::new(4); - let _y = x.clone(); - assert_eq!(Arc::try_unwrap(x), Err(Arc::new(4))); - let x = Arc::new(5); - let _w = Arc::downgrade(&x); - assert_eq!(Arc::try_unwrap(x), Ok(5)); -} - -#[test] -#[cfg_attr(any(target_os = "emscripten", target_os = "wasi"), ignore)] // no threads -fn into_inner() { - for _ in 0..100 - // ^ Increase chances of hitting potential race conditions - { - let x = Arc::new(3); - let y = Arc::clone(&x); - let r_thread = std::thread::spawn(|| Arc::into_inner(x)); - let s_thread = std::thread::spawn(|| Arc::into_inner(y)); - let r = r_thread.join().expect("r_thread panicked"); - let s = s_thread.join().expect("s_thread panicked"); - assert!( - matches!((r, s), (None, Some(3)) | (Some(3), None)), - "assertion failed: unexpected result `{:?}`\ - \n expected `(None, Some(3))` or `(Some(3), None)`", - (r, s), - ); - } - - let x = Arc::new(3); - assert_eq!(Arc::into_inner(x), Some(3)); - - let x = Arc::new(4); - let y = Arc::clone(&x); - assert_eq!(Arc::into_inner(x), None); - assert_eq!(Arc::into_inner(y), Some(4)); - - let x = Arc::new(5); - let _w = Arc::downgrade(&x); - assert_eq!(Arc::into_inner(x), Some(5)); -} - -#[test] -fn into_from_raw() { - let x = Arc::new(Box::new("hello")); - let y = x.clone(); - - let x_ptr = Arc::into_raw(x); - drop(y); - unsafe { - assert_eq!(**x_ptr, "hello"); - - let x = Arc::from_raw(x_ptr); - assert_eq!(**x, "hello"); - - assert_eq!(Arc::try_unwrap(x).map(|x| *x), Ok("hello")); - } -} - -#[test] -fn test_into_from_raw_unsized() { - use std::fmt::Display; - use std::string::ToString; - - let arc: Arc<str> = Arc::from("foo"); - - let ptr = Arc::into_raw(arc.clone()); - let arc2 = unsafe { Arc::from_raw(ptr) }; - - assert_eq!(unsafe { &*ptr }, "foo"); - assert_eq!(arc, arc2); - - let arc: Arc<dyn Display> = Arc::new(123); - - let ptr = Arc::into_raw(arc.clone()); - let arc2 = unsafe { Arc::from_raw(ptr) }; - - assert_eq!(unsafe { &*ptr }.to_string(), "123"); - assert_eq!(arc2.to_string(), "123"); -} - -#[test] -fn into_from_weak_raw() { - let x = Arc::new(Box::new("hello")); - let y = Arc::downgrade(&x); - - let y_ptr = Weak::into_raw(y); - unsafe { - assert_eq!(**y_ptr, "hello"); - - let y = Weak::from_raw(y_ptr); - let y_up = Weak::upgrade(&y).unwrap(); - assert_eq!(**y_up, "hello"); - drop(y_up); - - assert_eq!(Arc::try_unwrap(x).map(|x| *x), Ok("hello")); - } -} - -#[test] -fn test_into_from_weak_raw_unsized() { - use std::fmt::Display; - use std::string::ToString; - - let arc: Arc<str> = Arc::from("foo"); - let weak: Weak<str> = Arc::downgrade(&arc); - - let ptr = Weak::into_raw(weak.clone()); - let weak2 = unsafe { Weak::from_raw(ptr) }; - - assert_eq!(unsafe { &*ptr }, "foo"); - assert!(weak.ptr_eq(&weak2)); - - let arc: Arc<dyn Display> = Arc::new(123); - let weak: Weak<dyn Display> = Arc::downgrade(&arc); - - let ptr = Weak::into_raw(weak.clone()); - let weak2 = unsafe { Weak::from_raw(ptr) }; - - assert_eq!(unsafe { &*ptr }.to_string(), "123"); - assert!(weak.ptr_eq(&weak2)); -} - -#[test] -fn test_cowarc_clone_make_mut() { - let mut cow0 = Arc::new(75); - let mut cow1 = cow0.clone(); - let mut cow2 = cow1.clone(); - - assert!(75 == *Arc::make_mut(&mut cow0)); - assert!(75 == *Arc::make_mut(&mut cow1)); - assert!(75 == *Arc::make_mut(&mut cow2)); - - *Arc::make_mut(&mut cow0) += 1; - *Arc::make_mut(&mut cow1) += 2; - *Arc::make_mut(&mut cow2) += 3; - - assert!(76 == *cow0); - assert!(77 == *cow1); - assert!(78 == *cow2); - - // none should point to the same backing memory - assert!(*cow0 != *cow1); - assert!(*cow0 != *cow2); - assert!(*cow1 != *cow2); -} - -#[test] -fn test_cowarc_clone_unique2() { - let mut cow0 = Arc::new(75); - let cow1 = cow0.clone(); - let cow2 = cow1.clone(); - - assert!(75 == *cow0); - assert!(75 == *cow1); - assert!(75 == *cow2); - - *Arc::make_mut(&mut cow0) += 1; - assert!(76 == *cow0); - assert!(75 == *cow1); - assert!(75 == *cow2); - - // cow1 and cow2 should share the same contents - // cow0 should have a unique reference - assert!(*cow0 != *cow1); - assert!(*cow0 != *cow2); - assert!(*cow1 == *cow2); -} - -#[test] -fn test_cowarc_clone_weak() { - let mut cow0 = Arc::new(75); - let cow1_weak = Arc::downgrade(&cow0); - - assert!(75 == *cow0); - assert!(75 == *cow1_weak.upgrade().unwrap()); - - *Arc::make_mut(&mut cow0) += 1; - - assert!(76 == *cow0); - assert!(cow1_weak.upgrade().is_none()); -} - -#[test] -fn test_live() { - let x = Arc::new(5); - let y = Arc::downgrade(&x); - assert!(y.upgrade().is_some()); -} - -#[test] -fn test_dead() { - let x = Arc::new(5); - let y = Arc::downgrade(&x); - drop(x); - assert!(y.upgrade().is_none()); -} - -#[test] -fn weak_self_cyclic() { - struct Cycle { - x: Mutex<Option<Weak<Cycle>>>, - } - - let a = Arc::new(Cycle { x: Mutex::new(None) }); - let b = Arc::downgrade(&a.clone()); - *a.x.lock().unwrap() = Some(b); - - // hopefully we don't double-free (or leak)... -} - -#[test] -fn drop_arc() { - let mut canary = AtomicUsize::new(0); - let x = Arc::new(Canary(&mut canary as *mut AtomicUsize)); - drop(x); - assert!(canary.load(Acquire) == 1); -} - -#[test] -fn drop_arc_weak() { - let mut canary = AtomicUsize::new(0); - let arc = Arc::new(Canary(&mut canary as *mut AtomicUsize)); - let arc_weak = Arc::downgrade(&arc); - assert!(canary.load(Acquire) == 0); - drop(arc); - assert!(canary.load(Acquire) == 1); - drop(arc_weak); -} - -#[test] -fn test_strong_count() { - let a = Arc::new(0); - assert!(Arc::strong_count(&a) == 1); - let w = Arc::downgrade(&a); - assert!(Arc::strong_count(&a) == 1); - let b = w.upgrade().expect(""); - assert!(Arc::strong_count(&b) == 2); - assert!(Arc::strong_count(&a) == 2); - drop(w); - drop(a); - assert!(Arc::strong_count(&b) == 1); - let c = b.clone(); - assert!(Arc::strong_count(&b) == 2); - assert!(Arc::strong_count(&c) == 2); -} - -#[test] -fn test_weak_count() { - let a = Arc::new(0); - assert!(Arc::strong_count(&a) == 1); - assert!(Arc::weak_count(&a) == 0); - let w = Arc::downgrade(&a); - assert!(Arc::strong_count(&a) == 1); - assert!(Arc::weak_count(&a) == 1); - let x = w.clone(); - assert!(Arc::weak_count(&a) == 2); - drop(w); - drop(x); - assert!(Arc::strong_count(&a) == 1); - assert!(Arc::weak_count(&a) == 0); - let c = a.clone(); - assert!(Arc::strong_count(&a) == 2); - assert!(Arc::weak_count(&a) == 0); - let d = Arc::downgrade(&c); - assert!(Arc::weak_count(&c) == 1); - assert!(Arc::strong_count(&c) == 2); - - drop(a); - drop(c); - drop(d); -} - -#[test] -fn show_arc() { - let a = Arc::new(5); - assert_eq!(format!("{a:?}"), "5"); -} - -// Make sure deriving works with Arc<T> -#[derive(Eq, Ord, PartialEq, PartialOrd, Clone, Debug, Default)] -struct _Foo { - inner: Arc<i32>, -} - -#[test] -fn test_unsized() { - let x: Arc<[i32]> = Arc::new([1, 2, 3]); - assert_eq!(format!("{x:?}"), "[1, 2, 3]"); - let y = Arc::downgrade(&x.clone()); - drop(x); - assert!(y.upgrade().is_none()); -} - -#[test] -fn test_maybe_thin_unsized() { - // If/when custom thin DSTs exist, this test should be updated to use one - use std::ffi::CStr; - - let x: Arc<CStr> = Arc::from(c"swordfish"); - assert_eq!(format!("{x:?}"), "\"swordfish\""); - let y: Weak<CStr> = Arc::downgrade(&x); - drop(x); - - // At this point, the weak points to a dropped DST - assert!(y.upgrade().is_none()); - // But we still need to be able to get the alloc layout to drop. - // CStr has no drop glue, but custom DSTs might, and need to work. - drop(y); -} - -#[test] -fn test_from_owned() { - let foo = 123; - let foo_arc = Arc::from(foo); - assert!(123 == *foo_arc); -} - -#[test] -fn test_new_weak() { - let foo: Weak<usize> = Weak::new(); - assert!(foo.upgrade().is_none()); -} - -#[test] -fn test_ptr_eq() { - let five = Arc::new(5); - let same_five = five.clone(); - let other_five = Arc::new(5); - - assert!(Arc::ptr_eq(&five, &same_five)); - assert!(!Arc::ptr_eq(&five, &other_five)); -} - -#[test] -#[cfg_attr(target_os = "emscripten", ignore)] -fn test_weak_count_locked() { - let mut a = Arc::new(atomic::AtomicBool::new(false)); - let a2 = a.clone(); - let t = thread::spawn(move || { - // Miri is too slow - let count = if cfg!(miri) { 1000 } else { 1000000 }; - for _i in 0..count { - Arc::get_mut(&mut a); - } - a.store(true, SeqCst); - }); - - while !a2.load(SeqCst) { - let n = Arc::weak_count(&a2); - assert!(n < 2, "bad weak count: {}", n); - #[cfg(miri)] // Miri's scheduler does not guarantee liveness, and thus needs this hint. - std::hint::spin_loop(); - } - t.join().unwrap(); -} - -#[test] -fn test_from_str() { - let r: Arc<str> = Arc::from("foo"); - - assert_eq!(&r[..], "foo"); -} - -#[test] -fn test_copy_from_slice() { - let s: &[u32] = &[1, 2, 3]; - let r: Arc<[u32]> = Arc::from(s); - - assert_eq!(&r[..], [1, 2, 3]); -} - -#[test] -fn test_clone_from_slice() { - #[derive(Clone, Debug, Eq, PartialEq)] - struct X(u32); - - let s: &[X] = &[X(1), X(2), X(3)]; - let r: Arc<[X]> = Arc::from(s); - - assert_eq!(&r[..], s); -} - -#[test] -#[should_panic] -fn test_clone_from_slice_panic() { - use std::string::{String, ToString}; - - struct Fail(u32, String); - - impl Clone for Fail { - fn clone(&self) -> Fail { - if self.0 == 2 { - panic!(); - } - Fail(self.0, self.1.clone()) - } - } - - let s: &[Fail] = - &[Fail(0, "foo".to_string()), Fail(1, "bar".to_string()), Fail(2, "baz".to_string())]; - - // Should panic, but not cause memory corruption - let _r: Arc<[Fail]> = Arc::from(s); -} - -#[test] -fn test_from_box() { - let b: Box<u32> = Box::new(123); - let r: Arc<u32> = Arc::from(b); - - assert_eq!(*r, 123); -} - -#[test] -fn test_from_box_str() { - use std::string::String; - - let s = String::from("foo").into_boxed_str(); - let r: Arc<str> = Arc::from(s); - - assert_eq!(&r[..], "foo"); -} - -#[test] -fn test_from_box_slice() { - let s = vec![1, 2, 3].into_boxed_slice(); - let r: Arc<[u32]> = Arc::from(s); - - assert_eq!(&r[..], [1, 2, 3]); -} - -#[test] -fn test_from_box_trait() { - use std::fmt::Display; - use std::string::ToString; - - let b: Box<dyn Display> = Box::new(123); - let r: Arc<dyn Display> = Arc::from(b); - - assert_eq!(r.to_string(), "123"); -} - -#[test] -fn test_from_box_trait_zero_sized() { - use std::fmt::Debug; - - let b: Box<dyn Debug> = Box::new(()); - let r: Arc<dyn Debug> = Arc::from(b); - - assert_eq!(format!("{r:?}"), "()"); -} - -#[test] -fn test_from_vec() { - let v = vec![1, 2, 3]; - let r: Arc<[u32]> = Arc::from(v); - - assert_eq!(&r[..], [1, 2, 3]); -} - -#[test] -fn test_downcast() { - use std::any::Any; - - let r1: Arc<dyn Any + Send + Sync> = Arc::new(i32::MAX); - let r2: Arc<dyn Any + Send + Sync> = Arc::new("abc"); - - assert!(r1.clone().downcast::<u32>().is_err()); - - let r1i32 = r1.downcast::<i32>(); - assert!(r1i32.is_ok()); - assert_eq!(r1i32.unwrap(), Arc::new(i32::MAX)); - - assert!(r2.clone().downcast::<i32>().is_err()); - - let r2str = r2.downcast::<&'static str>(); - assert!(r2str.is_ok()); - assert_eq!(r2str.unwrap(), Arc::new("abc")); -} - -#[test] -fn test_array_from_slice() { - let v = vec![1, 2, 3]; - let r: Arc<[u32]> = Arc::from(v); - - let a: Result<Arc<[u32; 3]>, _> = r.clone().try_into(); - assert!(a.is_ok()); - - let a: Result<Arc<[u32; 2]>, _> = r.clone().try_into(); - assert!(a.is_err()); -} - -#[test] -fn test_arc_cyclic_with_zero_refs() { - struct ZeroRefs { - inner: Weak<ZeroRefs>, - } - let zero_refs = Arc::new_cyclic(|inner| { - assert_eq!(inner.strong_count(), 0); - assert!(inner.upgrade().is_none()); - ZeroRefs { inner: Weak::new() } - }); - - assert_eq!(Arc::strong_count(&zero_refs), 1); - assert_eq!(Arc::weak_count(&zero_refs), 0); - assert_eq!(zero_refs.inner.strong_count(), 0); - assert_eq!(zero_refs.inner.weak_count(), 0); -} - -#[test] -fn test_arc_new_cyclic_one_ref() { - struct OneRef { - inner: Weak<OneRef>, - } - let one_ref = Arc::new_cyclic(|inner| { - assert_eq!(inner.strong_count(), 0); - assert!(inner.upgrade().is_none()); - OneRef { inner: inner.clone() } - }); - - assert_eq!(Arc::strong_count(&one_ref), 1); - assert_eq!(Arc::weak_count(&one_ref), 1); - - let one_ref2 = Weak::upgrade(&one_ref.inner).unwrap(); - assert!(Arc::ptr_eq(&one_ref, &one_ref2)); - - assert_eq!(Arc::strong_count(&one_ref), 2); - assert_eq!(Arc::weak_count(&one_ref), 1); -} - -#[test] -fn test_arc_cyclic_two_refs() { - struct TwoRefs { - inner1: Weak<TwoRefs>, - inner2: Weak<TwoRefs>, - } - let two_refs = Arc::new_cyclic(|inner| { - assert_eq!(inner.strong_count(), 0); - assert!(inner.upgrade().is_none()); - - let inner1 = inner.clone(); - let inner2 = inner1.clone(); - - TwoRefs { inner1, inner2 } - }); - - assert_eq!(Arc::strong_count(&two_refs), 1); - assert_eq!(Arc::weak_count(&two_refs), 2); - - let two_refs1 = Weak::upgrade(&two_refs.inner1).unwrap(); - assert!(Arc::ptr_eq(&two_refs, &two_refs1)); - - let two_refs2 = Weak::upgrade(&two_refs.inner2).unwrap(); - assert!(Arc::ptr_eq(&two_refs, &two_refs2)); - - assert_eq!(Arc::strong_count(&two_refs), 3); - assert_eq!(Arc::weak_count(&two_refs), 2); -} - -/// Test for Arc::drop bug (https://github.com/rust-lang/rust/issues/55005) -#[test] -#[cfg(miri)] // relies on Stacked Borrows in Miri -fn arc_drop_dereferenceable_race() { - // The bug seems to take up to 700 iterations to reproduce with most seeds (tested 0-9). - for _ in 0..750 { - let arc_1 = Arc::new(()); - let arc_2 = arc_1.clone(); - let thread = thread::spawn(|| drop(arc_2)); - // Spin a bit; makes the race more likely to appear - let mut i = 0; - while i < 256 { - i += 1; - } - drop(arc_1); - thread.join().unwrap(); - } -} - -#[test] -fn arc_doesnt_leak_allocator() { - let counter = AtomicUsize::new(0); - - { - let arc: Arc<dyn Any + Send + Sync, _> = Arc::new_in(5usize, AllocCanary::new(&counter)); - drop(arc.downcast::<usize>().unwrap()); - - let arc: Arc<dyn Any + Send + Sync, _> = Arc::new_in(5usize, AllocCanary::new(&counter)); - drop(unsafe { arc.downcast_unchecked::<usize>() }); - - let arc = Arc::new_in(MaybeUninit::<usize>::new(5usize), AllocCanary::new(&counter)); - drop(unsafe { arc.assume_init() }); - - let arc: Arc<[MaybeUninit<usize>], _> = - Arc::new_zeroed_slice_in(5, AllocCanary::new(&counter)); - drop(unsafe { arc.assume_init() }); - } - - assert_eq!(counter.load(SeqCst), 0); -} diff --git a/library/alloc/tests/task.rs b/library/alloc/tests/task.rs deleted file mode 100644 index 390dec14484..00000000000 --- a/library/alloc/tests/task.rs +++ /dev/null @@ -1,36 +0,0 @@ -use alloc::rc::Rc; -use alloc::sync::Arc; -use alloc::task::{LocalWake, Wake}; -use core::task::{LocalWaker, Waker}; - -#[test] -#[cfg_attr(miri, ignore)] // `will_wake` doesn't guarantee that this test will work, and indeed on Miri it can fail -fn test_waker_will_wake_clone() { - struct NoopWaker; - - impl Wake for NoopWaker { - fn wake(self: Arc<Self>) {} - } - - let waker = Waker::from(Arc::new(NoopWaker)); - let clone = waker.clone(); - - assert!(waker.will_wake(&clone)); - assert!(clone.will_wake(&waker)); -} - -#[test] -#[cfg_attr(miri, ignore)] // `will_wake` doesn't guarantee that this test will work, and indeed on Miri it can fail -fn test_local_waker_will_wake_clone() { - struct NoopWaker; - - impl LocalWake for NoopWaker { - fn wake(self: Rc<Self>) {} - } - - let waker = LocalWaker::from(Rc::new(NoopWaker)); - let clone = waker.clone(); - - assert!(waker.will_wake(&clone)); - assert!(clone.will_wake(&waker)); -} diff --git a/library/alloc/tests/testing/crash_test.rs b/library/alloc/tests/testing/crash_test.rs deleted file mode 100644 index 502fe6c10c6..00000000000 --- a/library/alloc/tests/testing/crash_test.rs +++ /dev/null @@ -1,80 +0,0 @@ -use std::cmp::Ordering; -use std::fmt::Debug; -use std::sync::atomic::AtomicUsize; -use std::sync::atomic::Ordering::SeqCst; - -/// A blueprint for crash test dummy instances that monitor drops. -/// Some instances may be configured to panic at some point. -/// -/// Crash test dummies are identified and ordered by an id, so they can be used -/// as keys in a BTreeMap. -#[derive(Debug)] -pub struct CrashTestDummy { - pub id: usize, - dropped: AtomicUsize, -} - -impl CrashTestDummy { - /// Creates a crash test dummy design. The `id` determines order and equality of instances. - pub fn new(id: usize) -> CrashTestDummy { - CrashTestDummy { id, dropped: AtomicUsize::new(0) } - } - - /// Creates an instance of a crash test dummy that records what events it experiences - /// and optionally panics. - pub fn spawn(&self, panic: Panic) -> Instance<'_> { - Instance { origin: self, panic } - } - - /// Returns how many times instances of the dummy have been dropped. - pub fn dropped(&self) -> usize { - self.dropped.load(SeqCst) - } -} - -#[derive(Debug)] -pub struct Instance<'a> { - origin: &'a CrashTestDummy, - panic: Panic, -} - -#[derive(Copy, Clone, Debug, PartialEq, Eq)] -pub enum Panic { - Never, - InDrop, -} - -impl Instance<'_> { - pub fn id(&self) -> usize { - self.origin.id - } -} - -impl Drop for Instance<'_> { - fn drop(&mut self) { - self.origin.dropped.fetch_add(1, SeqCst); - if self.panic == Panic::InDrop { - panic!("panic in `drop`"); - } - } -} - -impl PartialOrd for Instance<'_> { - fn partial_cmp(&self, other: &Self) -> Option<Ordering> { - self.id().partial_cmp(&other.id()) - } -} - -impl Ord for Instance<'_> { - fn cmp(&self, other: &Self) -> Ordering { - self.id().cmp(&other.id()) - } -} - -impl PartialEq for Instance<'_> { - fn eq(&self, other: &Self) -> bool { - self.id().eq(&other.id()) - } -} - -impl Eq for Instance<'_> {} diff --git a/library/alloc/tests/testing/mod.rs b/library/alloc/tests/testing/mod.rs deleted file mode 100644 index 0a3dd191dc8..00000000000 --- a/library/alloc/tests/testing/mod.rs +++ /dev/null @@ -1 +0,0 @@ -pub mod crash_test; diff --git a/library/alloc/tests/thin_box.rs b/library/alloc/tests/thin_box.rs deleted file mode 100644 index 4c46b614127..00000000000 --- a/library/alloc/tests/thin_box.rs +++ /dev/null @@ -1,261 +0,0 @@ -use core::fmt::Debug; -use std::boxed::ThinBox; - -#[test] -fn want_niche_optimization() { - fn uses_niche<T: ?Sized>() -> bool { - size_of::<*const ()>() == size_of::<Option<ThinBox<T>>>() - } - - trait Tr {} - assert!(uses_niche::<dyn Tr>()); - assert!(uses_niche::<[i32]>()); - assert!(uses_niche::<i32>()); -} - -#[test] -fn want_thin() { - fn is_thin<T: ?Sized>() -> bool { - size_of::<*const ()>() == size_of::<ThinBox<T>>() - } - - trait Tr {} - assert!(is_thin::<dyn Tr>()); - assert!(is_thin::<[i32]>()); - assert!(is_thin::<i32>()); -} - -#[allow(dead_code)] -fn assert_covariance() { - fn thin_box<'new>(b: ThinBox<[&'static str]>) -> ThinBox<[&'new str]> { - b - } -} - -#[track_caller] -fn verify_aligned<T>(ptr: *const T) { - // Use `black_box` to attempt to obscure the fact that we're calling this - // function on pointers that come from box/references, which the compiler - // would otherwise realize is impossible (because it would mean we've - // already executed UB). - // - // That is, we'd *like* it to be possible for the asserts in this function - // to detect brokenness in the ThinBox impl. - // - // It would probably be better if we instead had these as debug_asserts - // inside `ThinBox`, prior to the point where we do the UB. Anyway, in - // practice these checks are mostly just smoke-detectors for an extremely - // broken `ThinBox` impl, since it's an extremely subtle piece of code. - let ptr = core::hint::black_box(ptr); - assert!( - ptr.is_aligned() && !ptr.is_null(), - "misaligned ThinBox data; valid pointers to `{ty}` should be aligned to {align}: {ptr:p}", - ty = core::any::type_name::<T>(), - align = align_of::<T>(), - ); -} - -#[track_caller] -fn check_thin_sized<T: Debug + PartialEq + Clone>(make: impl FnOnce() -> T) { - let value = make(); - let boxed = ThinBox::new(value.clone()); - let val = &*boxed; - verify_aligned(val as *const T); - assert_eq!(val, &value); -} - -#[track_caller] -fn check_thin_dyn<T: Debug + PartialEq + Clone>(make: impl FnOnce() -> T) { - let value = make(); - let wanted_debug = format!("{value:?}"); - let boxed: ThinBox<dyn Debug> = ThinBox::new_unsize(value.clone()); - let val = &*boxed; - // wide reference -> wide pointer -> thin pointer - verify_aligned(val as *const dyn Debug as *const T); - let got_debug = format!("{val:?}"); - assert_eq!(wanted_debug, got_debug); -} - -macro_rules! define_test { - ( - @test_name: $testname:ident; - - $(#[$m:meta])* - struct $Type:ident($inner:ty); - - $($test_stmts:tt)* - ) => { - #[test] - fn $testname() { - use core::sync::atomic::{AtomicIsize, Ordering}; - // Define the type, and implement new/clone/drop in such a way that - // the number of live instances will be counted. - $(#[$m])* - #[derive(Debug, PartialEq)] - struct $Type { - _priv: $inner, - } - - impl Clone for $Type { - fn clone(&self) -> Self { - verify_aligned(self); - Self::new(self._priv.clone()) - } - } - - impl Drop for $Type { - fn drop(&mut self) { - verify_aligned(self); - Self::modify_live(-1); - } - } - - impl $Type { - fn new(i: $inner) -> Self { - Self::modify_live(1); - Self { _priv: i } - } - - fn modify_live(n: isize) -> isize { - static COUNTER: AtomicIsize = AtomicIsize::new(0); - COUNTER.fetch_add(n, Ordering::Relaxed) + n - } - - fn live_objects() -> isize { - Self::modify_live(0) - } - } - // Run the test statements - let _: () = { $($test_stmts)* }; - // Check that we didn't leak anything, or call drop too many times. - assert_eq!( - $Type::live_objects(), 0, - "Wrong number of drops of {}, `initializations - drops` should be 0.", - stringify!($Type), - ); - } - }; -} - -define_test! { - @test_name: align1zst; - struct Align1Zst(()); - - check_thin_sized(|| Align1Zst::new(())); - check_thin_dyn(|| Align1Zst::new(())); -} - -define_test! { - @test_name: align1small; - struct Align1Small(u8); - - check_thin_sized(|| Align1Small::new(50)); - check_thin_dyn(|| Align1Small::new(50)); -} - -define_test! { - @test_name: align1_size_not_pow2; - struct Align64NotPow2Size([u8; 79]); - - check_thin_sized(|| Align64NotPow2Size::new([100; 79])); - check_thin_dyn(|| Align64NotPow2Size::new([100; 79])); -} - -define_test! { - @test_name: align1big; - struct Align1Big([u8; 256]); - - check_thin_sized(|| Align1Big::new([5u8; 256])); - check_thin_dyn(|| Align1Big::new([5u8; 256])); -} - -// Note: `#[repr(align(2))]` is worth testing because -// - can have pointers which are misaligned, unlike align(1) -// - is still expected to have an alignment less than the alignment of a vtable. -define_test! { - @test_name: align2zst; - #[repr(align(2))] - struct Align2Zst(()); - - check_thin_sized(|| Align2Zst::new(())); - check_thin_dyn(|| Align2Zst::new(())); -} - -define_test! { - @test_name: align2small; - #[repr(align(2))] - struct Align2Small(u8); - - check_thin_sized(|| Align2Small::new(60)); - check_thin_dyn(|| Align2Small::new(60)); -} - -define_test! { - @test_name: align2full; - #[repr(align(2))] - struct Align2Full([u8; 2]); - check_thin_sized(|| Align2Full::new([3u8; 2])); - check_thin_dyn(|| Align2Full::new([3u8; 2])); -} - -define_test! { - @test_name: align2_size_not_pow2; - #[repr(align(2))] - struct Align2NotPower2Size([u8; 6]); - - check_thin_sized(|| Align2NotPower2Size::new([3; 6])); - check_thin_dyn(|| Align2NotPower2Size::new([3; 6])); -} - -define_test! { - @test_name: align2big; - #[repr(align(2))] - struct Align2Big([u8; 256]); - - check_thin_sized(|| Align2Big::new([5u8; 256])); - check_thin_dyn(|| Align2Big::new([5u8; 256])); -} - -define_test! { - @test_name: align64zst; - #[repr(align(64))] - struct Align64Zst(()); - - check_thin_sized(|| Align64Zst::new(())); - check_thin_dyn(|| Align64Zst::new(())); -} - -define_test! { - @test_name: align64small; - #[repr(align(64))] - struct Align64Small(u8); - - check_thin_sized(|| Align64Small::new(50)); - check_thin_dyn(|| Align64Small::new(50)); -} - -define_test! { - @test_name: align64med; - #[repr(align(64))] - struct Align64Med([u8; 64]); - check_thin_sized(|| Align64Med::new([10; 64])); - check_thin_dyn(|| Align64Med::new([10; 64])); -} - -define_test! { - @test_name: align64_size_not_pow2; - #[repr(align(64))] - struct Align64NotPow2Size([u8; 192]); - - check_thin_sized(|| Align64NotPow2Size::new([10; 192])); - check_thin_dyn(|| Align64NotPow2Size::new([10; 192])); -} - -define_test! { - @test_name: align64big; - #[repr(align(64))] - struct Align64Big([u8; 256]); - - check_thin_sized(|| Align64Big::new([10; 256])); - check_thin_dyn(|| Align64Big::new([10; 256])); -} diff --git a/library/alloc/tests/vec.rs b/library/alloc/tests/vec.rs deleted file mode 100644 index f430d979fa8..00000000000 --- a/library/alloc/tests/vec.rs +++ /dev/null @@ -1,2750 +0,0 @@ -// FIXME(static_mut_refs): Do not allow `static_mut_refs` lint -#![allow(static_mut_refs)] - -use core::alloc::{Allocator, Layout}; -use core::num::NonZero; -use core::ptr::NonNull; -use core::{assert_eq, assert_ne}; -use std::alloc::System; -use std::assert_matches::assert_matches; -use std::borrow::Cow; -use std::cell::Cell; -use std::collections::TryReserveErrorKind::*; -use std::fmt::Debug; -use std::hint; -use std::iter::InPlaceIterable; -use std::mem::swap; -use std::ops::Bound::*; -use std::panic::{AssertUnwindSafe, catch_unwind}; -use std::rc::Rc; -use std::sync::atomic::{AtomicU32, Ordering}; -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_indexing() { - let v: Vec<isize> = vec![10, 20]; - assert_eq!(v[0], 10); - assert_eq!(v[1], 20); - let mut x: usize = 0; - assert_eq!(v[x], 10); - assert_eq!(v[x + 1], 20); - x = x + 1; - assert_eq!(v[x], 20); - assert_eq!(v[x - 1], 10); -} - -#[test] -fn test_debug_fmt() { - let vec1: Vec<isize> = vec![]; - assert_eq!("[]", format!("{:?}", vec1)); - - let vec2 = vec![0, 1]; - assert_eq!("[0, 1]", format!("{:?}", vec2)); - - let slice: &[isize] = &[4, 5]; - assert_eq!("[4, 5]", format!("{slice:?}")); -} - -#[test] -fn test_push() { - let mut v = vec![]; - v.push(1); - assert_eq!(v, [1]); - v.push(2); - assert_eq!(v, [1, 2]); - v.push(3); - assert_eq!(v, [1, 2, 3]); -} - -#[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_from_slice() { - let a: Vec<isize> = vec![1, 2, 3, 4, 5]; - let b: Vec<isize> = vec![6, 7, 8, 9, 0]; - - let mut v: Vec<isize> = a; - - v.extend_from_slice(&b); - - assert_eq!(v, [1, 2, 3, 4, 5, 6, 7, 8, 9, 0]); -} - -#[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_ref() { - let values = vec![1, 2, 3, 4, 5]; - let slice = &values[1..3]; - - assert_eq!(slice, [2, 3]); -} - -#[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::new(1), Box::new(2), Box::new(3)]; - let two: Vec<Box<_>> = vec![Box::new(4), Box::new(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_retain_predicate_order() { - for to_keep in [true, false] { - let mut number_of_executions = 0; - let mut vec = vec![1, 2, 3, 4]; - let mut next_expected = 1; - vec.retain(|&x| { - assert_eq!(next_expected, x); - next_expected += 1; - number_of_executions += 1; - to_keep - }); - assert_eq!(number_of_executions, 4); - } -} - -#[test] -#[cfg_attr(not(panic = "unwind"), ignore = "test requires unwinding support")] -fn test_retain_pred_panic_with_hole() { - let v = (0..5).map(Rc::new).collect::<Vec<_>>(); - catch_unwind(AssertUnwindSafe(|| { - let mut v = v.clone(); - v.retain(|r| match **r { - 0 => true, - 1 => false, - 2 => true, - _ => panic!(), - }); - })) - .unwrap_err(); - // Everything is dropped when predicate panicked. - assert!(v.iter().all(|r| Rc::strong_count(r) == 1)); -} - -#[test] -#[cfg_attr(not(panic = "unwind"), ignore = "test requires unwinding support")] -fn test_retain_pred_panic_no_hole() { - let v = (0..5).map(Rc::new).collect::<Vec<_>>(); - catch_unwind(AssertUnwindSafe(|| { - let mut v = v.clone(); - v.retain(|r| match **r { - 0 | 1 | 2 => true, - _ => panic!(), - }); - })) - .unwrap_err(); - // Everything is dropped when predicate panicked. - assert!(v.iter().all(|r| Rc::strong_count(r) == 1)); -} - -#[test] -#[cfg_attr(not(panic = "unwind"), ignore = "test requires unwinding support")] -fn test_retain_drop_panic() { - struct Wrap(Rc<i32>); - - impl Drop for Wrap { - fn drop(&mut self) { - if *self.0 == 3 { - panic!(); - } - } - } - - let v = (0..5).map(|x| Rc::new(x)).collect::<Vec<_>>(); - catch_unwind(AssertUnwindSafe(|| { - let mut v = v.iter().map(|r| Wrap(r.clone())).collect::<Vec<_>>(); - v.retain(|w| match *w.0 { - 0 => true, - 1 => false, - 2 => true, - 3 => false, // Drop panic. - _ => true, - }); - })) - .unwrap_err(); - // Other elements are dropped when `drop` of one element panicked. - // The panicked wrapper also has its Rc dropped. - assert!(v.iter().all(|r| Rc::strong_count(r) == 1)); -} - -#[test] -fn test_retain_maybeuninits() { - // This test aimed to be run under miri. - use core::mem::MaybeUninit; - let mut vec: Vec<_> = [1i32, 2, 3, 4].map(|v| MaybeUninit::new(vec![v])).into(); - vec.retain(|x| { - // SAFETY: Retain must visit every element of Vec in original order and exactly once. - // Our values is initialized at creation of Vec. - let v = unsafe { x.assume_init_ref()[0] }; - if v & 1 == 0 { - return true; - } - // SAFETY: Value is initialized. - // Value wouldn't be dropped by `Vec::retain` - // because `MaybeUninit` doesn't drop content. - drop(unsafe { x.assume_init_read() }); - false - }); - let vec: Vec<i32> = vec - .into_iter() - .map(|x| unsafe { - // SAFETY: All values dropped in retain predicate must be removed by `Vec::retain`. - // Remaining values are initialized. - x.assume_init()[0] - }) - .collect(); - 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::new(1), Box::new(1), Box::new(2), Box::new(3)]; - v0.dedup(); - let mut v1: Vec<Box<_>> = vec![Box::new(1), Box::new(2), Box::new(2), Box::new(3)]; - v1.dedup(); - let mut v2: Vec<Box<_>> = vec![Box::new(1), Box::new(2), Box::new(3), Box::new(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!([].into_iter().partition(|x: &i32| *x < 3), (vec![], vec![])); - assert_eq!([1, 2, 3].into_iter().partition(|x| *x < 4), (vec![1, 2, 3], vec![])); - assert_eq!([1, 2, 3].into_iter().partition(|x| *x < 2), (vec![1], vec![2, 3])); - assert_eq!([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_cmp() { - let x: &[isize] = &[1, 2, 3, 4, 5]; - let cmp: &[isize] = &[1, 2, 3, 4, 5]; - assert_eq!(&x[..], cmp); - let cmp: &[isize] = &[3, 4, 5]; - assert_eq!(&x[2..], cmp); - let cmp: &[isize] = &[1, 2, 3]; - assert_eq!(&x[..3], cmp); - let cmp: &[isize] = &[2, 3, 4]; - assert_eq!(&x[1..4], cmp); - - let x: Vec<isize> = vec![1, 2, 3, 4, 5]; - let cmp: &[isize] = &[1, 2, 3, 4, 5]; - assert_eq!(&x[..], cmp); - let cmp: &[isize] = &[3, 4, 5]; - assert_eq!(&x[2..], cmp); - let cmp: &[isize] = &[1, 2, 3]; - assert_eq!(&x[..3], cmp); - let cmp: &[isize] = &[2, 3, 4]; - assert_eq!(&x[1..4], cmp); -} - -#[test] -fn test_vec_truncate_drop() { - static mut DROPS: u32 = 0; - struct Elem(#[allow(dead_code)] 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]; - let _ = &x[!0..]; -} - -#[test] -#[should_panic] -fn test_slice_out_of_bounds_2() { - let x = vec![1, 2, 3, 4, 5]; - let _ = &x[..6]; -} - -#[test] -#[should_panic] -fn test_slice_out_of_bounds_3() { - let x = vec![1, 2, 3, 4, 5]; - let _ = &x[!0..4]; -} - -#[test] -#[should_panic] -fn test_slice_out_of_bounds_4() { - let x = vec![1, 2, 3, 4, 5]; - let _ = &x[1..6]; -} - -#[test] -#[should_panic] -fn test_slice_out_of_bounds_5() { - let x = vec![1, 2, 3, 4, 5]; - let _ = &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_empty_vec() { - let mut vec: Vec<i32> = vec![]; - let mut vec2: Vec<i32> = vec![]; - for i in vec.drain(..) { - vec2.push(i); - } - assert!(vec.is_empty()); - assert!(vec2.is_empty()); -} - -#[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_index_overflow() { - let mut v = Vec::<()>::with_capacity(usize::MAX); - unsafe { - v.set_len(usize::MAX); - } - v.drain(0..=usize::MAX); -} - -#[test] -#[should_panic] -fn test_drain_inclusive_out_of_bounds() { - let mut v = vec![1, 2, 3, 4, 5]; - v.drain(5..=5); -} - -#[test] -#[should_panic] -fn test_drain_start_overflow() { - let mut v = vec![1, 2, 3]; - v.drain((Excluded(usize::MAX), Included(0))); -} - -#[test] -#[should_panic] -fn test_drain_end_overflow() { - let mut v = vec![1, 2, 3]; - v.drain((Included(0), Included(usize::MAX))); -} - -#[test] -#[cfg_attr(not(panic = "unwind"), ignore = "test requires unwinding support")] -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_drain_keep_rest() { - let mut v = vec![0, 1, 2, 3, 4, 5, 6]; - let mut drain = v.drain(1..6); - assert_eq!(drain.next(), Some(1)); - assert_eq!(drain.next_back(), Some(5)); - assert_eq!(drain.next(), Some(2)); - - drain.keep_rest(); - assert_eq!(v, &[0, 3, 4, 6]); -} - -#[test] -fn test_drain_keep_rest_all() { - let mut v = vec![0, 1, 2, 3, 4, 5, 6]; - v.drain(1..6).keep_rest(); - assert_eq!(v, &[0, 1, 2, 3, 4, 5, 6]); -} - -#[test] -fn test_drain_keep_rest_none() { - let mut v = vec![0, 1, 2, 3, 4, 5, 6]; - let mut drain = v.drain(1..6); - - drain.by_ref().for_each(drop); - - drain.keep_rest(); - assert_eq!(v, &[0, 6]); -} - -#[test] -fn test_splice() { - let mut v = vec![1, 2, 3, 4, 5]; - let a = [10, 11, 12]; - v.splice(2..4, a); - 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).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); -} - -#[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); -} - -#[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)); - 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 orig_ptr = vec.as_ptr(); - let orig_capacity = vec.capacity(); - - let split_off = vec.split_off(4); - assert_eq!(vec, [1, 2, 3, 4]); - assert_eq!(split_off, [5, 6]); - assert_eq!(vec.capacity(), orig_capacity); - assert_eq!(vec.as_ptr(), orig_ptr); -} - -#[test] -fn test_split_off_take_all() { - // Allocate enough capacity that we can tell whether the split-off vector's - // capacity is based on its size, or (incorrectly) on the original capacity. - let mut vec = Vec::with_capacity(1000); - vec.extend([1, 2, 3, 4, 5, 6]); - let orig_ptr = vec.as_ptr(); - let orig_capacity = vec.capacity(); - - let split_off = vec.split_off(0); - assert_eq!(vec, []); - assert_eq!(split_off, [1, 2, 3, 4, 5, 6]); - assert_eq!(vec.capacity(), orig_capacity); - assert_eq!(vec.as_ptr(), orig_ptr); - - // The split-off vector should be newly-allocated, and should not have - // stolen the original vector's allocation. - assert!(split_off.capacity() < orig_capacity); - assert_ne!(split_off.as_ptr(), orig_ptr); -} - -#[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!([1, 2, 3].into_iter().count(), 3); -} - -#[test] -fn test_into_iter_next_chunk() { - let mut iter = b"lorem".to_vec().into_iter(); - - assert_eq!(iter.next_chunk().unwrap(), [b'l', b'o']); // N is inferred as 2 - assert_eq!(iter.next_chunk().unwrap(), [b'r', b'e', b'm']); // N is inferred as 3 - assert_eq!(iter.next_chunk::<4>().unwrap_err().as_slice(), &[]); // N is explicitly 4 -} - -#[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 = [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] -#[cfg_attr(not(panic = "unwind"), ignore = "test requires unwinding support")] -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_into_iter_advance_by() { - let mut i = vec![1, 2, 3, 4, 5].into_iter(); - assert_eq!(i.advance_by(0), Ok(())); - assert_eq!(i.advance_back_by(0), Ok(())); - assert_eq!(i.as_slice(), [1, 2, 3, 4, 5]); - - assert_eq!(i.advance_by(1), Ok(())); - assert_eq!(i.advance_back_by(1), Ok(())); - assert_eq!(i.as_slice(), [2, 3, 4]); - - assert_eq!(i.advance_back_by(usize::MAX), Err(NonZero::new(usize::MAX - 3).unwrap())); - - assert_eq!(i.advance_by(usize::MAX), Err(NonZero::new(usize::MAX).unwrap())); - - assert_eq!(i.advance_by(0), Ok(())); - assert_eq!(i.advance_back_by(0), Ok(())); - - assert_eq!(i.len(), 0); -} - -#[test] -fn test_into_iter_drop_allocator() { - struct ReferenceCountedAllocator<'a>(#[allow(dead_code)] DropCounter<'a>); - - unsafe impl Allocator for ReferenceCountedAllocator<'_> { - fn allocate(&self, layout: Layout) -> Result<NonNull<[u8]>, core::alloc::AllocError> { - System.allocate(layout) - } - - unsafe fn deallocate(&self, ptr: NonNull<u8>, layout: Layout) { - // Safety: Invariants passed to caller. - unsafe { System.deallocate(ptr, layout) } - } - } - - let mut drop_count = 0; - - let allocator = ReferenceCountedAllocator(DropCounter { count: &mut drop_count }); - let _ = Vec::<u32, _>::new_in(allocator); - assert_eq!(drop_count, 1); - - let allocator = ReferenceCountedAllocator(DropCounter { count: &mut drop_count }); - let _ = Vec::<u32, _>::new_in(allocator).into_iter(); - assert_eq!(drop_count, 2); -} - -#[test] -fn test_into_iter_zst() { - #[derive(Debug, Clone)] - struct AlignedZstWithDrop([u64; 0]); - impl Drop for AlignedZstWithDrop { - fn drop(&mut self) { - let addr = self as *mut _ as usize; - assert!(hint::black_box(addr) % align_of::<u64>() == 0); - } - } - - const C: AlignedZstWithDrop = AlignedZstWithDrop([0u64; 0]); - - for _ in vec![C].into_iter() {} - for _ in vec![C; 5].into_iter().rev() {} - - let mut it = vec![C, C].into_iter(); - assert_eq!(it.advance_by(1), Ok(())); - drop(it); - - let mut it = vec![C, C].into_iter(); - it.next_chunk::<1>().unwrap(); - drop(it); - - let mut it = vec![C, C].into_iter(); - it.next_chunk::<4>().unwrap_err(); - drop(it); -} - -#[test] -fn test_from_iter_specialization() { - let src: Vec<usize> = vec![0usize; 1]; - let srcptr = src.as_ptr(); - let sink = src.into_iter().collect::<Vec<_>>(); - let sinkptr = sink.as_ptr(); - assert_eq!(srcptr, sinkptr); -} - -#[test] -fn test_from_iter_partially_drained_in_place_specialization() { - let src: Vec<usize> = vec![0usize; 10]; - let srcptr = src.as_ptr(); - let mut iter = src.into_iter(); - iter.next(); - iter.next(); - let sink = iter.collect::<Vec<_>>(); - let sinkptr = sink.as_ptr(); - assert_eq!(srcptr, sinkptr); -} - -#[test] -fn test_from_iter_specialization_with_iterator_adapters() { - fn assert_in_place_trait<T: InPlaceIterable>(_: &T) {} - let owned: Vec<usize> = vec![0usize; 256]; - let refd: Vec<&usize> = owned.iter().collect(); - let src: Vec<&&usize> = refd.iter().collect(); - let srcptr = src.as_ptr(); - let iter = src - .into_iter() - .copied() - .cloned() - .enumerate() - .map(|i| i.0 + i.1) - .zip(std::iter::repeat(1usize)) - .map(|(a, b)| a + b) - .map_while(Option::Some) - .skip(1) - .map(|e| if e != usize::MAX { Ok(NonZero::new(e)) } else { Err(()) }); - assert_in_place_trait(&iter); - let sink = iter.collect::<Result<Vec<_>, _>>().unwrap(); - let sinkptr = sink.as_ptr(); - assert_eq!(srcptr as *const usize, sinkptr as *const usize); -} - -#[test] -fn test_in_place_specialization_step_up_down() { - fn assert_in_place_trait<T: InPlaceIterable>(_: &T) {} - - let src = vec![0u8; 1024]; - let srcptr = src.as_ptr(); - let src_bytes = src.capacity(); - let iter = src.into_iter().array_chunks::<4>(); - assert_in_place_trait(&iter); - let sink = iter.collect::<Vec<_>>(); - let sinkptr = sink.as_ptr(); - assert_eq!(srcptr.addr(), sinkptr.addr()); - assert_eq!(src_bytes, sink.capacity() * 4); - - let mut src: Vec<u8> = Vec::with_capacity(17); - let src_bytes = src.capacity(); - src.resize(8, 0u8); - let sink: Vec<[u8; 4]> = src.into_iter().array_chunks::<4>().collect(); - let sink_bytes = sink.capacity() * 4; - assert_ne!(src_bytes, sink_bytes); - assert_eq!(sink.len(), 2); - - let mut src: Vec<[u8; 3]> = Vec::with_capacity(17); - src.resize(8, [0; 3]); - let iter = src.into_iter().map(|[a, b, _]| [a, b]); - assert_in_place_trait(&iter); - let sink: Vec<[u8; 2]> = iter.collect(); - assert_eq!(sink.len(), 8); - assert!(sink.capacity() <= 25); -} - -#[test] -fn test_from_iter_specialization_head_tail_drop() { - let drop_count: Vec<_> = (0..=2).map(|_| Rc::new(())).collect(); - let src: Vec<_> = drop_count.iter().cloned().collect(); - let srcptr = src.as_ptr(); - let iter = src.into_iter(); - let sink: Vec<_> = iter.skip(1).take(1).collect(); - let sinkptr = sink.as_ptr(); - assert_eq!(srcptr, sinkptr, "specialization was applied"); - assert_eq!(Rc::strong_count(&drop_count[0]), 1, "front was dropped"); - assert_eq!(Rc::strong_count(&drop_count[1]), 2, "one element was collected"); - assert_eq!(Rc::strong_count(&drop_count[2]), 1, "tail was dropped"); - assert_eq!(sink.len(), 1); -} - -#[test] -#[cfg_attr(not(panic = "unwind"), ignore = "test requires unwinding support")] -fn test_from_iter_specialization_panic_during_iteration_drops() { - let drop_count: Vec<_> = (0..=2).map(|_| Rc::new(())).collect(); - let src: Vec<_> = drop_count.iter().cloned().collect(); - let iter = src.into_iter(); - - let _ = std::panic::catch_unwind(AssertUnwindSafe(|| { - let _ = iter - .enumerate() - .filter_map(|(i, e)| { - if i == 1 { - std::panic!("aborting iteration"); - } - Some(e) - }) - .collect::<Vec<_>>(); - })); - - assert!( - drop_count.iter().map(Rc::strong_count).all(|count| count == 1), - "all items were dropped once" - ); -} - -#[test] -#[cfg_attr(not(panic = "unwind"), ignore = "test requires unwinding support")] -// FIXME(static_mut_refs): Do not allow `static_mut_refs` lint -#[allow(static_mut_refs)] -fn test_from_iter_specialization_panic_during_drop_doesnt_leak() { - static mut DROP_COUNTER_OLD: [usize; 5] = [0; 5]; - static mut DROP_COUNTER_NEW: [usize; 2] = [0; 2]; - - #[derive(Debug)] - struct Old(usize); - - impl Drop for Old { - fn drop(&mut self) { - unsafe { - DROP_COUNTER_OLD[self.0] += 1; - } - - if self.0 == 3 { - panic!(); - } - - println!("Dropped Old: {}", self.0); - } - } - - #[derive(Debug)] - struct New(usize); - - impl Drop for New { - fn drop(&mut self) { - unsafe { - DROP_COUNTER_NEW[self.0] += 1; - } - - println!("Dropped New: {}", self.0); - } - } - - let _ = std::panic::catch_unwind(AssertUnwindSafe(|| { - let v = vec![Old(0), Old(1), Old(2), Old(3), Old(4)]; - let _ = v.into_iter().map(|x| New(x.0)).take(2).collect::<Vec<_>>(); - })); - - assert_eq!(unsafe { DROP_COUNTER_OLD[0] }, 1); - assert_eq!(unsafe { DROP_COUNTER_OLD[1] }, 1); - assert_eq!(unsafe { DROP_COUNTER_OLD[2] }, 1); - assert_eq!(unsafe { DROP_COUNTER_OLD[3] }, 1); - assert_eq!(unsafe { DROP_COUNTER_OLD[4] }, 1); - - assert_eq!(unsafe { DROP_COUNTER_NEW[0] }, 1); - assert_eq!(unsafe { DROP_COUNTER_NEW[1] }, 1); -} - -// regression test for issue #85322. Peekable previously implemented InPlaceIterable, -// but due to an interaction with IntoIter's current Clone implementation it failed to uphold -// the contract. -#[test] -fn test_collect_after_iterator_clone() { - let v = vec![0; 5]; - let mut i = v.into_iter().map(|i| i + 1).peekable(); - i.peek(); - let v = i.clone().collect::<Vec<_>>(); - assert_eq!(v, [1, 1, 1, 1, 1]); - assert!(v.len() <= v.capacity()); -} - -// regression test for #135103, similar to the one above Flatten/FlatMap had an unsound InPlaceIterable -// implementation. -#[test] -fn test_flatten_clone() { - const S: String = String::new(); - - let v = vec![[S, "Hello World!".into()], [S, S]]; - let mut i = v.into_iter().flatten(); - let _ = i.next(); - let result: Vec<String> = i.clone().collect(); - assert_eq!(result, ["Hello World!", "", ""]); -} - -#[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 extract_if_empty() { - let mut vec: Vec<i32> = vec![]; - - { - let mut iter = vec.extract_if(.., |_| 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 extract_if_zst() { - let mut vec = vec![(), (), (), (), ()]; - let initial_len = vec.len(); - let mut count = 0; - { - let mut iter = vec.extract_if(.., |_| 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 extract_if_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.extract_if(.., |_| 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 extract_if_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.extract_if(.., |_| 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 extract_if_ranges() { - let mut vec = vec![0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10]; - - let mut count = 0; - let it = vec.extract_if(1..=3, |_| { - count += 1; - true - }); - assert_eq!(it.collect::<Vec<_>>(), vec![1, 2, 3]); - assert_eq!(vec, vec![0, 4, 5, 6, 7, 8, 9, 10]); - assert_eq!(count, 3); - - let it = vec.extract_if(1..=3, |_| false); - assert_eq!(it.collect::<Vec<_>>(), vec![]); - assert_eq!(vec, vec![0, 4, 5, 6, 7, 8, 9, 10]); -} - -#[test] -#[should_panic] -fn extract_if_out_of_bounds() { - let mut vec = vec![0, 1]; - let _ = vec.extract_if(5.., |_| true).for_each(drop); -} - -#[test] -fn extract_if_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.extract_if(.., |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.extract_if(.., |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.extract_if(.., |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.extract_if(.., |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.extract_if(.., |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]); - } -} - -#[test] -#[cfg_attr(not(panic = "unwind"), ignore = "test requires unwinding support")] -fn extract_if_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.extract_if(.., filter); - - // NOTE: The ExtractIf 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); - } -} - -#[test] -#[cfg_attr(not(panic = "unwind"), ignore = "test requires unwinding support")] -fn extract_if_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.extract_if(.., filter); - - // NOTE: The ExtractIf 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 extract_if_unconsumed() { - let mut vec = vec![1, 2, 3, 4]; - let drain = vec.extract_if(.., |&mut x| x % 2 != 0); - drop(drain); - assert_eq!(vec, [1, 2, 3, 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 -fn test_try_with_capacity() { - let mut vec: Vec<u32> = Vec::try_with_capacity(5).unwrap(); - assert_eq!(0, vec.len()); - assert!(vec.capacity() >= 5 && vec.capacity() <= isize::MAX as usize / 4); - assert!(vec.spare_capacity_mut().len() >= 5); - - assert!(Vec::<u16>::try_with_capacity(isize::MAX as usize + 1).is_err()); -} - -#[test] -#[cfg_attr(miri, ignore)] // Miri does not support signalling OOM -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; - - { - // 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).map_err(|e| e.kind()) { - 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).map_err(|e| e.kind()) { - panic!("isize::MAX shouldn't trigger an overflow!"); - } - - // Check isize::MAX + 1 does count as overflow - assert_matches!( - empty_bytes.try_reserve(MAX_CAP + 1).map_err(|e| e.kind()), - Err(CapacityOverflow), - "isize::MAX + 1 should trigger an overflow!" - ); - - // Check usize::MAX does count as overflow - assert_matches!( - empty_bytes.try_reserve(MAX_USIZE).map_err(|e| e.kind()), - Err(CapacityOverflow), - "usize::MAX should trigger an overflow!" - ); - } - - { - // 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).map_err(|e| e.kind()) { - panic!("isize::MAX shouldn't trigger an overflow!"); - } - if let Err(CapacityOverflow) = ten_bytes.try_reserve(MAX_CAP - 10).map_err(|e| e.kind()) { - panic!("isize::MAX shouldn't trigger an overflow!"); - } - - assert_matches!( - ten_bytes.try_reserve(MAX_CAP - 9).map_err(|e| e.kind()), - Err(CapacityOverflow), - "isize::MAX + 1 should trigger an overflow!" - ); - - // Should always overflow in the add-to-len - assert_matches!( - ten_bytes.try_reserve(MAX_USIZE).map_err(|e| e.kind()), - Err(CapacityOverflow), - "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).map_err(|e| e.kind()) - { - panic!("isize::MAX shouldn't trigger an overflow!"); - } - if let Err(CapacityOverflow) = ten_u32s.try_reserve(MAX_CAP / 4 - 10).map_err(|e| e.kind()) - { - panic!("isize::MAX shouldn't trigger an overflow!"); - } - - assert_matches!( - ten_u32s.try_reserve(MAX_CAP / 4 - 9).map_err(|e| e.kind()), - Err(CapacityOverflow), - "isize::MAX + 1 should trigger an overflow!" - ); - - // Should fail in the mul-by-size - assert_matches!( - ten_u32s.try_reserve(MAX_USIZE - 20).map_err(|e| e.kind()), - Err(CapacityOverflow), - "usize::MAX should trigger an overflow!" - ); - } -} - -#[test] -#[cfg_attr(miri, ignore)] // Miri does not support signalling OOM -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 mut empty_bytes: Vec<u8> = Vec::new(); - - if let Err(CapacityOverflow) = empty_bytes.try_reserve_exact(MAX_CAP).map_err(|e| e.kind()) - { - panic!("isize::MAX shouldn't trigger an overflow!"); - } - if let Err(CapacityOverflow) = empty_bytes.try_reserve_exact(MAX_CAP).map_err(|e| e.kind()) - { - panic!("isize::MAX shouldn't trigger an overflow!"); - } - - assert_matches!( - empty_bytes.try_reserve_exact(MAX_CAP + 1).map_err(|e| e.kind()), - Err(CapacityOverflow), - "isize::MAX + 1 should trigger an overflow!" - ); - - assert_matches!( - empty_bytes.try_reserve_exact(MAX_USIZE).map_err(|e| e.kind()), - Err(CapacityOverflow), - "usize::MAX should trigger an overflow!" - ); - } - - { - 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).map_err(|e| e.kind()) - { - panic!("isize::MAX shouldn't trigger an overflow!"); - } - if let Err(CapacityOverflow) = - ten_bytes.try_reserve_exact(MAX_CAP - 10).map_err(|e| e.kind()) - { - panic!("isize::MAX shouldn't trigger an overflow!"); - } - - assert_matches!( - ten_bytes.try_reserve_exact(MAX_CAP - 9).map_err(|e| e.kind()), - Err(CapacityOverflow), - "isize::MAX + 1 should trigger an overflow!" - ); - - assert_matches!( - ten_bytes.try_reserve_exact(MAX_USIZE).map_err(|e| e.kind()), - Err(CapacityOverflow), - "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).map_err(|e| e.kind()) - { - panic!("isize::MAX shouldn't trigger an overflow!"); - } - if let Err(CapacityOverflow) = - ten_u32s.try_reserve_exact(MAX_CAP / 4 - 10).map_err(|e| e.kind()) - { - panic!("isize::MAX shouldn't trigger an overflow!"); - } - - assert_matches!( - ten_u32s.try_reserve_exact(MAX_CAP / 4 - 9).map_err(|e| e.kind()), - Err(CapacityOverflow), - "isize::MAX + 1 should trigger an overflow!" - ); - - assert_matches!( - ten_u32s.try_reserve_exact(MAX_USIZE - 20).map_err(|e| e.kind()), - Err(CapacityOverflow), - "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. - // Note that this test does *not* constitute a stable guarantee that all these functions do not - // reallocate! Only what is explicitly documented at - // <https://doc.rust-lang.org/nightly/std/vec/struct.Vec.html#guarantees> is stably guaranteed. - 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, [1; 10].into_iter().filter(|_| true))); // lower bound not exact - assert_eq!(*v0, 13); - - // spare_capacity_mut - v.spare_capacity_mut(); - assert_eq!(*v0, 13); - - // Smoke test that would fire even outside Miri if an actual relocation happened. - // Also ensures the pointer is still writeable after all this. - *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!(std::ptr::eq(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:expr, $a3:expr; $b2:expr, $b3: expr) => { - 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); - assert_partial_eq_valid!(vec2,vec3; arrayref2[..],arrayref3[..]); -} - -#[test] -fn test_vec_cycle() { - #[derive(Debug)] - struct C<'a> { - v: Vec<Cell<Option<&'a C<'a>>>>, - } - - impl<'a> C<'a> { - fn new() -> C<'a> { - C { v: Vec::new() } - } - } - - let mut c1 = C::new(); - let mut c2 = C::new(); - let mut c3 = C::new(); - - // Push - c1.v.push(Cell::new(None)); - c1.v.push(Cell::new(None)); - - c2.v.push(Cell::new(None)); - c2.v.push(Cell::new(None)); - - c3.v.push(Cell::new(None)); - c3.v.push(Cell::new(None)); - - // Set - c1.v[0].set(Some(&c2)); - c1.v[1].set(Some(&c3)); - - c2.v[0].set(Some(&c2)); - c2.v[1].set(Some(&c3)); - - c3.v[0].set(Some(&c1)); - c3.v[1].set(Some(&c2)); -} - -#[test] -fn test_vec_cycle_wrapped() { - struct Refs<'a> { - v: Vec<Cell<Option<&'a C<'a>>>>, - } - - struct C<'a> { - refs: Refs<'a>, - } - - impl<'a> Refs<'a> { - fn new() -> Refs<'a> { - Refs { v: Vec::new() } - } - } - - impl<'a> C<'a> { - fn new() -> C<'a> { - C { refs: Refs::new() } - } - } - - let mut c1 = C::new(); - let mut c2 = C::new(); - let mut c3 = C::new(); - - c1.refs.v.push(Cell::new(None)); - c1.refs.v.push(Cell::new(None)); - c2.refs.v.push(Cell::new(None)); - c2.refs.v.push(Cell::new(None)); - c3.refs.v.push(Cell::new(None)); - c3.refs.v.push(Cell::new(None)); - - c1.refs.v[0].set(Some(&c2)); - c1.refs.v[1].set(Some(&c3)); - c2.refs.v[0].set(Some(&c2)); - c2.refs.v[1].set(Some(&c3)); - c3.refs.v[0].set(Some(&c1)); - c3.refs.v[1].set(Some(&c2)); -} - -#[test] -fn test_zero_sized_capacity() { - for len in [0, 1, 2, 4, 8, 16, 32, 64, 128, 256] { - let v = Vec::<()>::with_capacity(len); - assert_eq!(v.len(), 0); - assert_eq!(v.capacity(), usize::MAX); - } -} - -#[test] -fn test_zero_sized_vec_push() { - const N: usize = 8; - - for len in 0..N { - let mut tester = Vec::with_capacity(len); - assert_eq!(tester.len(), 0); - assert!(tester.capacity() >= len); - for _ in 0..len { - tester.push(()); - } - assert_eq!(tester.len(), len); - assert_eq!(tester.iter().count(), len); - tester.clear(); - } -} - -#[test] -fn test_vec_macro_repeat() { - assert_eq!(vec![1; 3], vec![1, 1, 1]); - assert_eq!(vec![1; 2], vec![1, 1]); - assert_eq!(vec![1; 1], vec![1]); - assert_eq!(vec![1; 0], vec![]); - - // from_elem syntax (see RFC 832) - let el = Box::new(1); - let n = 3; - assert_eq!(vec![el; n], vec![Box::new(1), Box::new(1), Box::new(1)]); -} - -#[test] -fn test_vec_swap() { - let mut a: Vec<isize> = vec![0, 1, 2, 3, 4, 5, 6]; - a.swap(2, 4); - assert_eq!(a[2], 4); - assert_eq!(a[4], 2); - let mut n = 42; - swap(&mut n, &mut a[0]); - assert_eq!(a[0], 42); - assert_eq!(n, 0); -} - -#[test] -fn test_extend_from_within_spec() { - #[derive(Copy)] - struct CopyOnly; - - impl Clone for CopyOnly { - fn clone(&self) -> Self { - panic!("extend_from_within must use specialization on copy"); - } - } - - vec![CopyOnly, CopyOnly].extend_from_within(..); -} - -#[test] -fn test_extend_from_within_clone() { - let mut v = vec![String::from("sssss"), String::from("12334567890"), String::from("c")]; - v.extend_from_within(1..); - - assert_eq!(v, ["sssss", "12334567890", "c", "12334567890", "c"]); -} - -#[test] -fn test_extend_from_within_complete_rande() { - let mut v = vec![0, 1, 2, 3]; - v.extend_from_within(..); - - assert_eq!(v, [0, 1, 2, 3, 0, 1, 2, 3]); -} - -#[test] -fn test_extend_from_within_empty_rande() { - let mut v = vec![0, 1, 2, 3]; - v.extend_from_within(1..1); - - assert_eq!(v, [0, 1, 2, 3]); -} - -#[test] -#[should_panic] -fn test_extend_from_within_out_of_rande() { - let mut v = vec![0, 1]; - v.extend_from_within(..3); -} - -#[test] -fn test_extend_from_within_zst() { - let mut v = vec![(); 8]; - v.extend_from_within(3..7); - - assert_eq!(v, [(); 12]); -} - -#[test] -fn test_extend_from_within_empty_vec() { - let mut v = Vec::<i32>::new(); - v.extend_from_within(..); - - assert_eq!(v, []); -} - -#[test] -fn test_extend_from_within() { - let mut v = vec![String::from("a"), String::from("b"), String::from("c")]; - v.extend_from_within(1..=2); - v.extend_from_within(..=1); - - assert_eq!(v, ["a", "b", "c", "b", "c", "a", "b"]); -} - -#[test] -fn test_vec_dedup_by() { - let mut vec: Vec<i32> = vec![1, -1, 2, 3, 1, -5, 5, -2, 2]; - - vec.dedup_by(|a, b| a.abs() == b.abs()); - - assert_eq!(vec, [1, 2, 3, 1, -5, -2]); -} - -#[test] -fn test_vec_dedup_empty() { - let mut vec: Vec<i32> = Vec::new(); - - vec.dedup(); - - assert_eq!(vec, []); -} - -#[test] -fn test_vec_dedup_one() { - let mut vec = vec![12i32]; - - vec.dedup(); - - assert_eq!(vec, [12]); -} - -#[test] -fn test_vec_dedup_multiple_ident() { - let mut vec = vec![12, 12, 12, 12, 12, 11, 11, 11, 11, 11, 11]; - - vec.dedup(); - - assert_eq!(vec, [12, 11]); -} - -#[test] -fn test_vec_dedup_partialeq() { - #[derive(Debug)] - struct Foo(i32, #[allow(dead_code)] i32); - - impl PartialEq for Foo { - fn eq(&self, other: &Foo) -> bool { - self.0 == other.0 - } - } - - let mut vec = vec![Foo(0, 1), Foo(0, 5), Foo(1, 7), Foo(1, 9)]; - - vec.dedup(); - assert_eq!(vec, [Foo(0, 1), Foo(1, 7)]); -} - -#[test] -fn test_vec_dedup() { - let mut vec: Vec<bool> = Vec::with_capacity(8); - let mut template = vec.clone(); - - for x in 0u8..255u8 { - vec.clear(); - template.clear(); - - let iter = (0..8).map(move |bit| (x >> bit) & 1 == 1); - vec.extend(iter); - template.extend_from_slice(&vec); - - let (dedup, _) = template.partition_dedup(); - vec.dedup(); - - assert_eq!(vec, dedup); - } -} - -#[test] -#[cfg_attr(not(panic = "unwind"), ignore = "test requires unwinding support")] -fn test_vec_dedup_panicking() { - #[derive(Debug)] - struct Panic<'a> { - drop_counter: &'a Cell<u32>, - value: bool, - index: usize, - } - - impl<'a> PartialEq for Panic<'a> { - fn eq(&self, other: &Self) -> bool { - self.value == other.value - } - } - - impl<'a> Drop for Panic<'a> { - fn drop(&mut self) { - self.drop_counter.set(self.drop_counter.get() + 1); - if !std::thread::panicking() { - assert!(self.index != 4); - } - } - } - - let drop_counter = &Cell::new(0); - let expected = [ - Panic { drop_counter, value: false, index: 0 }, - Panic { drop_counter, value: false, index: 5 }, - Panic { drop_counter, value: true, index: 6 }, - Panic { drop_counter, value: true, index: 7 }, - ]; - let mut vec = vec![ - Panic { drop_counter, value: false, index: 0 }, - // these elements get deduplicated - Panic { drop_counter, value: false, index: 1 }, - Panic { drop_counter, value: false, index: 2 }, - Panic { drop_counter, value: false, index: 3 }, - Panic { drop_counter, value: false, index: 4 }, - // here it panics while dropping the item with index==4 - Panic { drop_counter, value: false, index: 5 }, - Panic { drop_counter, value: true, index: 6 }, - Panic { drop_counter, value: true, index: 7 }, - ]; - - let _ = catch_unwind(AssertUnwindSafe(|| vec.dedup())).unwrap_err(); - - assert_eq!(drop_counter.get(), 4); - - let ok = vec.iter().zip(expected.iter()).all(|(x, y)| x.index == y.index); - - if !ok { - panic!("expected: {expected:?}\ngot: {vec:?}\n"); - } -} - -// Regression test for issue #82533 -#[test] -#[cfg_attr(not(panic = "unwind"), ignore = "test requires unwinding support")] -fn test_extend_from_within_panicking_clone() { - struct Panic<'dc> { - drop_count: &'dc AtomicU32, - aaaaa: bool, - } - - impl Clone for Panic<'_> { - fn clone(&self) -> Self { - if self.aaaaa { - panic!("panic! at the clone"); - } - - Self { ..*self } - } - } - - impl Drop for Panic<'_> { - fn drop(&mut self) { - self.drop_count.fetch_add(1, Ordering::SeqCst); - } - } - - let count = core::sync::atomic::AtomicU32::new(0); - let mut vec = vec![ - Panic { drop_count: &count, aaaaa: false }, - Panic { drop_count: &count, aaaaa: true }, - Panic { drop_count: &count, aaaaa: false }, - ]; - - // This should clone&append one Panic{..} at the end, and then panic while - // cloning second Panic{..}. This means that `Panic::drop` should be called - // 4 times (3 for items already in vector, 1 for just appended). - // - // Previously just appended item was leaked, making drop_count = 3, instead of 4. - std::panic::catch_unwind(move || vec.extend_from_within(..)).unwrap_err(); - - assert_eq!(count.load(Ordering::SeqCst), 4); -} - -#[test] -#[should_panic = "vec len overflow"] -fn test_into_flattened_size_overflow() { - let v = vec![[(); usize::MAX]; 2]; - let _ = v.into_flattened(); -} - -#[test] -fn test_box_zero_allocator() { - use core::alloc::AllocError; - use core::cell::RefCell; - use std::collections::HashSet; - - // Track ZST allocations and ensure that they all have a matching free. - struct ZstTracker { - state: RefCell<(HashSet<usize>, usize)>, - } - unsafe impl Allocator for ZstTracker { - fn allocate(&self, layout: Layout) -> Result<NonNull<[u8]>, AllocError> { - let ptr = if layout.size() == 0 { - let mut state = self.state.borrow_mut(); - let addr = state.1; - assert!(state.0.insert(addr)); - state.1 += 1; - std::println!("allocating {addr}"); - std::ptr::without_provenance_mut(addr) - } else { - unsafe { std::alloc::alloc(layout) } - }; - Ok(NonNull::slice_from_raw_parts(NonNull::new(ptr).ok_or(AllocError)?, layout.size())) - } - - unsafe fn deallocate(&self, ptr: NonNull<u8>, layout: Layout) { - if layout.size() == 0 { - let addr = ptr.as_ptr() as usize; - let mut state = self.state.borrow_mut(); - std::println!("freeing {addr}"); - assert!(state.0.remove(&addr), "ZST free that wasn't allocated"); - } else { - unsafe { std::alloc::dealloc(ptr.as_ptr(), layout) } - } - } - } - - // Start the state at 100 to avoid returning null pointers. - let alloc = ZstTracker { state: RefCell::new((HashSet::new(), 100)) }; - - // Ensure that unsizing retains the same behavior. - { - let b1: Box<[u8; 0], &ZstTracker> = Box::new_in([], &alloc); - let b2: Box<[u8], &ZstTracker> = b1.clone(); - let _b3: Box<[u8], &ZstTracker> = b2.clone(); - } - - // Ensure that shrinking doesn't leak a ZST allocation. - { - let mut v1: Vec<u8, &ZstTracker> = Vec::with_capacity_in(100, &alloc); - v1.shrink_to_fit(); - } - - // Ensure that conversion to/from vec works. - { - let v1: Vec<(), &ZstTracker> = Vec::with_capacity_in(100, &alloc); - let _b1: Box<[()], &ZstTracker> = v1.into_boxed_slice(); - let b2: Box<[()], &ZstTracker> = Box::new_in([(), (), ()], &alloc); - let _v2: Vec<(), &ZstTracker> = b2.into(); - } - - // Ensure all ZSTs have been freed. - assert!(alloc.state.borrow().0.is_empty()); -} - -#[test] -fn test_vec_from_array_ref() { - assert_eq!(Vec::from(&[1, 2, 3]), vec![1, 2, 3]); -} - -#[test] -fn test_vec_from_array_mut_ref() { - assert_eq!(Vec::from(&mut [1, 2, 3]), vec![1, 2, 3]); -} - -#[test] -fn test_pop_if() { - let mut v = vec![1, 2, 3, 4]; - let pred = |x: &mut i32| *x % 2 == 0; - - assert_eq!(v.pop_if(pred), Some(4)); - assert_eq!(v, [1, 2, 3]); - - assert_eq!(v.pop_if(pred), None); - assert_eq!(v, [1, 2, 3]); -} - -#[test] -fn test_pop_if_empty() { - let mut v = Vec::<i32>::new(); - assert_eq!(v.pop_if(|_| true), None); - assert!(v.is_empty()); -} - -#[test] -fn test_pop_if_mutates() { - let mut v = vec![1]; - let pred = |x: &mut i32| { - *x += 1; - false - }; - assert_eq!(v.pop_if(pred), None); - assert_eq!(v, [2]); -} - -/// This assortment of tests, in combination with miri, verifies we handle UB on fishy arguments -/// in the stdlib. Draining and extending the allocation are fairly well-tested earlier, but -/// `vec.insert(usize::MAX, val)` once slipped by! -/// -/// All code that manipulates the collection types should be tested with "trivially wrong" args. -#[test] -fn max_dont_panic() { - let mut v = vec![0]; - let _ = v.get(usize::MAX); - v.shrink_to(usize::MAX); - v.truncate(usize::MAX); -} - -#[test] -#[should_panic] -fn max_insert() { - let mut v = vec![0]; - v.insert(usize::MAX, 1); -} - -#[test] -#[should_panic] -fn max_remove() { - let mut v = vec![0]; - v.remove(usize::MAX); -} - -#[test] -#[should_panic] -fn max_splice() { - let mut v = vec![0]; - v.splice(usize::MAX.., core::iter::once(1)); -} - -#[test] -#[should_panic] -fn max_swap_remove() { - let mut v = vec![0]; - v.swap_remove(usize::MAX); -} - -// Regression test for #135338 -#[test] -fn vec_null_ptr_roundtrip() { - let ptr = std::ptr::from_ref(&42); - let zero = ptr.with_addr(0); - let roundtripped = vec![zero; 1].pop().unwrap(); - let new = roundtripped.with_addr(ptr.addr()); - unsafe { new.read() }; -} diff --git a/library/alloc/tests/vec_deque.rs b/library/alloc/tests/vec_deque.rs deleted file mode 100644 index 1b03c29e5bd..00000000000 --- a/library/alloc/tests/vec_deque.rs +++ /dev/null @@ -1,1865 +0,0 @@ -// FIXME(static_mut_refs): Do not allow `static_mut_refs` lint -#![allow(static_mut_refs)] - -use core::num::NonZero; -use std::assert_matches::assert_matches; -use std::collections::TryReserveErrorKind::*; -use std::collections::VecDeque; -use std::collections::vec_deque::Drain; -use std::fmt::Debug; -use std::ops::Bound::*; -use std::panic::{AssertUnwindSafe, catch_unwind}; - -use Taggy::*; -use Taggypar::*; - -use crate::hash; - -#[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_pop_if() { - let mut deq: VecDeque<_> = vec![0, 1, 2, 3, 4].into(); - let pred = |x: &mut i32| *x % 2 == 0; - - assert_eq!(deq.pop_front_if(pred), Some(0)); - assert_eq!(deq, [1, 2, 3, 4]); - - assert_eq!(deq.pop_front_if(pred), None); - assert_eq!(deq, [1, 2, 3, 4]); - - assert_eq!(deq.pop_back_if(pred), Some(4)); - assert_eq!(deq, [1, 2, 3]); - - assert_eq!(deq.pop_back_if(pred), None); - assert_eq!(deq, [1, 2, 3]); -} - -#[test] -fn test_pop_if_empty() { - let mut deq = VecDeque::<i32>::new(); - assert_eq!(deq.pop_front_if(|_| true), None); - assert_eq!(deq.pop_back_if(|_| true), None); - assert!(deq.is_empty()); -} - -#[test] -fn test_pop_if_mutates() { - let mut v: VecDeque<_> = vec![-1, 1].into(); - let pred = |x: &mut i32| { - *x *= 2; - false - }; - assert_eq!(v.pop_front_if(pred), None); - assert_eq!(v, [-2, 1]); - assert_eq!(v.pop_back_if(pred), None); - assert_eq!(v, [-2, 2]); -} - -#[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]; -} - -#[test] -#[should_panic] -fn test_range_start_overflow() { - let deq = VecDeque::from(vec![1, 2, 3]); - deq.range((Included(0), Included(usize::MAX))); -} - -#[test] -#[should_panic] -fn test_range_end_overflow() { - let deq = VecDeque::from(vec![1, 2, 3]); - deq.range((Excluded(usize::MAX), Included(0))); -} - -#[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))); - } - - // advance_by - { - let mut d = VecDeque::new(); - for i in 0..=4 { - d.push_back(i); - } - for i in 6..=8 { - d.push_front(i); - } - - let mut it = d.into_iter(); - assert_eq!(it.advance_by(1), Ok(())); - assert_eq!(it.next(), Some(7)); - assert_eq!(it.advance_back_by(1), Ok(())); - assert_eq!(it.next_back(), Some(3)); - - let mut it = VecDeque::from(vec![1, 2, 3, 4, 5]).into_iter(); - assert_eq!(it.advance_by(10), Err(NonZero::new(5).unwrap())); - let mut it = VecDeque::from(vec![1, 2, 3, 4, 5]).into_iter(); - assert_eq!(it.advance_back_by(10), Err(NonZero::new(5).unwrap())); - } -} - -#[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] -#[cfg_attr(not(panic = "unwind"), ignore = "test requires unwinding support")] -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<_> = [1, 2, 3].into_iter().collect(); - let mut b: VecDeque<_> = [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] -#[should_panic] -fn test_append_zst_capacity_overflow() { - let mut v = Vec::with_capacity(usize::MAX); - // note: using resize instead of set_len here would - // be *extremely* slow in unoptimized builds. - // SAFETY: `v` has capacity `usize::MAX`, and no initialization - // is needed for empty tuples. - unsafe { v.set_len(usize::MAX) }; - let mut v = VecDeque::from(v); - let mut w = vec![()].into(); - v.append(&mut w); -} - -#[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() >= 33) -} - -#[test] -#[cfg_attr(miri, ignore)] // Miri does not support signalling OOM -fn test_try_with_capacity() { - let vec: VecDeque<u32> = VecDeque::try_with_capacity(5).unwrap(); - assert_eq!(0, vec.len()); - assert!(vec.capacity() >= 5 && vec.capacity() <= isize::MAX as usize / 4); - - assert!(VecDeque::<u16>::try_with_capacity(isize::MAX as usize + 1).is_err()); -} - -#[test] -#[cfg_attr(miri, ignore)] // Miri does not support signalling OOM -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; - - { - // 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).map_err(|e| e.kind()) { - 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).map_err(|e| e.kind()) { - panic!("isize::MAX shouldn't trigger an overflow!"); - } - - // Check isize::MAX + 1 does count as overflow - assert_matches!( - empty_bytes.try_reserve(MAX_CAP + 1).map_err(|e| e.kind()), - Err(CapacityOverflow), - "isize::MAX + 1 should trigger an overflow!" - ); - - // Check usize::MAX does count as overflow - assert_matches!( - empty_bytes.try_reserve(MAX_USIZE).map_err(|e| e.kind()), - Err(CapacityOverflow), - "usize::MAX should trigger an overflow!" - ); - } - - { - // Same basic idea, but with non-zero len - let mut ten_bytes: VecDeque<u8> = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10].into_iter().collect(); - - if let Err(CapacityOverflow) = ten_bytes.try_reserve(MAX_CAP - 10).map_err(|e| e.kind()) { - panic!("isize::MAX shouldn't trigger an overflow!"); - } - if let Err(CapacityOverflow) = ten_bytes.try_reserve(MAX_CAP - 10).map_err(|e| e.kind()) { - panic!("isize::MAX shouldn't trigger an overflow!"); - } - - assert_matches!( - ten_bytes.try_reserve(MAX_CAP - 9).map_err(|e| e.kind()), - Err(CapacityOverflow), - "isize::MAX + 1 should trigger an overflow!" - ); - - // Should always overflow in the add-to-len - assert_matches!( - ten_bytes.try_reserve(MAX_USIZE).map_err(|e| e.kind()), - Err(CapacityOverflow), - "usize::MAX should trigger an overflow!" - ); - } - - { - // Same basic idea, but with interesting type size - let mut ten_u32s: VecDeque<u32> = [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).map_err(|e| e.kind()) - { - panic!("isize::MAX shouldn't trigger an overflow!"); - } - if let Err(CapacityOverflow) = ten_u32s.try_reserve(MAX_CAP / 4 - 10).map_err(|e| e.kind()) - { - panic!("isize::MAX shouldn't trigger an overflow!"); - } - - assert_matches!( - ten_u32s.try_reserve(MAX_CAP / 4 - 9).map_err(|e| e.kind()), - Err(CapacityOverflow), - "isize::MAX + 1 should trigger an overflow!" - ); - - // Should fail in the mul-by-size - assert_matches!( - ten_u32s.try_reserve(MAX_USIZE - 20).map_err(|e| e.kind()), - Err(CapacityOverflow), - "usize::MAX should trigger an overflow!" - ); - } -} - -#[test] -#[cfg_attr(miri, ignore)] // Miri does not support signalling OOM -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 mut empty_bytes: VecDeque<u8> = VecDeque::new(); - - if let Err(CapacityOverflow) = empty_bytes.try_reserve_exact(MAX_CAP).map_err(|e| e.kind()) - { - panic!("isize::MAX shouldn't trigger an overflow!"); - } - if let Err(CapacityOverflow) = empty_bytes.try_reserve_exact(MAX_CAP).map_err(|e| e.kind()) - { - panic!("isize::MAX shouldn't trigger an overflow!"); - } - - assert_matches!( - empty_bytes.try_reserve_exact(MAX_CAP + 1).map_err(|e| e.kind()), - Err(CapacityOverflow), - "isize::MAX + 1 should trigger an overflow!" - ); - - assert_matches!( - empty_bytes.try_reserve_exact(MAX_USIZE).map_err(|e| e.kind()), - Err(CapacityOverflow), - "usize::MAX should trigger an overflow!" - ); - } - - { - let mut ten_bytes: VecDeque<u8> = [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).map_err(|e| e.kind()) - { - panic!("isize::MAX shouldn't trigger an overflow!"); - } - if let Err(CapacityOverflow) = - ten_bytes.try_reserve_exact(MAX_CAP - 10).map_err(|e| e.kind()) - { - panic!("isize::MAX shouldn't trigger an overflow!"); - } - - assert_matches!( - ten_bytes.try_reserve_exact(MAX_CAP - 9).map_err(|e| e.kind()), - Err(CapacityOverflow), - "isize::MAX + 1 should trigger an overflow!" - ); - - assert_matches!( - ten_bytes.try_reserve_exact(MAX_USIZE).map_err(|e| e.kind()), - Err(CapacityOverflow), - "usize::MAX should trigger an overflow!" - ); - } - - { - let mut ten_u32s: VecDeque<u32> = [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).map_err(|e| e.kind()) - { - panic!("isize::MAX shouldn't trigger an overflow!"); - } - if let Err(CapacityOverflow) = - ten_u32s.try_reserve_exact(MAX_CAP / 4 - 10).map_err(|e| e.kind()) - { - panic!("isize::MAX shouldn't trigger an overflow!"); - } - - assert_matches!( - ten_u32s.try_reserve_exact(MAX_CAP / 4 - 9).map_err(|e| e.kind()), - Err(CapacityOverflow), - "isize::MAX + 1 should trigger an overflow!" - ); - - assert_matches!( - ten_u32s.try_reserve_exact(MAX_USIZE - 20).map_err(|e| e.kind()), - Err(CapacityOverflow), - "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<_> = VecDeque::with_capacity(8); - v.extend(1..=7); - 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<_> = VecDeque::with_capacity(8); - v.extend(1..=7); - 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] -#[cfg_attr(not(panic = "unwind"), ignore = "test requires unwinding support")] -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] -#[cfg_attr(not(panic = "unwind"), ignore = "test requires unwinding support")] -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); -} - -#[test] -fn test_binary_search() { - // Contiguous (front only) search: - let deque: VecDeque<_> = vec![1, 2, 3, 5, 6].into(); - assert!(deque.as_slices().1.is_empty()); - assert_eq!(deque.binary_search(&3), Ok(2)); - assert_eq!(deque.binary_search(&4), Err(3)); - - // Split search (both front & back non-empty): - let mut deque: VecDeque<_> = vec![5, 6].into(); - deque.push_front(3); - deque.push_front(2); - deque.push_front(1); - deque.push_back(10); - assert!(!deque.as_slices().0.is_empty()); - assert!(!deque.as_slices().1.is_empty()); - assert_eq!(deque.binary_search(&0), Err(0)); - assert_eq!(deque.binary_search(&1), Ok(0)); - assert_eq!(deque.binary_search(&5), Ok(3)); - assert_eq!(deque.binary_search(&7), Err(5)); - assert_eq!(deque.binary_search(&20), Err(6)); -} - -#[test] -fn test_binary_search_by() { - let deque: VecDeque<_> = vec![(1,), (2,), (3,), (5,), (6,)].into(); - - assert_eq!(deque.binary_search_by(|&(v,)| v.cmp(&3)), Ok(2)); - assert_eq!(deque.binary_search_by(|&(v,)| v.cmp(&4)), Err(3)); -} - -#[test] -fn test_binary_search_by_key() { - let deque: VecDeque<_> = vec![(1,), (2,), (3,), (5,), (6,)].into(); - - assert_eq!(deque.binary_search_by_key(&3, |&(v,)| v), Ok(2)); - assert_eq!(deque.binary_search_by_key(&4, |&(v,)| v), Err(3)); -} - -#[test] -fn test_partition_point() { - // Contiguous (front only) search: - let deque: VecDeque<_> = vec![1, 2, 3, 5, 6].into(); - assert!(deque.as_slices().1.is_empty()); - assert_eq!(deque.partition_point(|&v| v <= 3), 3); - - // Split search (both front & back non-empty): - let mut deque: VecDeque<_> = vec![5, 6].into(); - deque.push_front(3); - deque.push_front(2); - deque.push_front(1); - deque.push_back(10); - assert!(!deque.as_slices().0.is_empty()); - assert!(!deque.as_slices().1.is_empty()); - assert_eq!(deque.partition_point(|&v| v <= 5), 4); -} - -#[test] -fn test_zero_sized_push() { - const N: usize = 8; - - // Zero sized type - struct Zst; - - // Test that for all possible sequences of push_front / push_back, - // we end up with a deque of the correct size - - for len in 0..N { - let mut tester = VecDeque::with_capacity(len); - assert_eq!(tester.len(), 0); - assert!(tester.capacity() >= len); - for case in 0..(1 << len) { - assert_eq!(tester.len(), 0); - for bit in 0..len { - if case & (1 << bit) != 0 { - tester.push_front(Zst); - } else { - tester.push_back(Zst); - } - } - assert_eq!(tester.len(), len); - assert_eq!(tester.iter().count(), len); - tester.clear(); - } - } -} - -#[test] -fn test_from_zero_sized_vec() { - let v = vec![(); 100]; - let queue = VecDeque::from(v); - assert_eq!(queue.len(), 100); -} - -#[test] -fn test_resize_keeps_reserved_space_from_item() { - let v = Vec::<i32>::with_capacity(1234); - let mut d = VecDeque::new(); - d.resize(1, v); - assert_eq!(d[0].capacity(), 1234); -} - -#[test] -fn test_collect_from_into_iter_keeps_allocation() { - let mut v = Vec::with_capacity(13); - v.extend(0..7); - check(v.as_ptr(), v.last().unwrap(), v.into_iter()); - - let mut v = VecDeque::with_capacity(13); - v.extend(0..7); - check(&v[0], &v[v.len() - 1], v.into_iter()); - - fn check(buf: *const i32, last: *const i32, mut it: impl Iterator<Item = i32>) { - assert_eq!(it.next(), Some(0)); - assert_eq!(it.next(), Some(1)); - - let mut v: VecDeque<i32> = it.collect(); - assert_eq!(v.capacity(), 13); - assert_eq!(v.as_slices().0.as_ptr(), buf.wrapping_add(2)); - assert_eq!(&v[v.len() - 1] as *const _, last); - - assert_eq!(v.as_slices(), ([2, 3, 4, 5, 6].as_slice(), [].as_slice())); - v.push_front(7); - assert_eq!(v.as_slices(), ([7, 2, 3, 4, 5, 6].as_slice(), [].as_slice())); - v.push_front(8); - assert_eq!(v.as_slices(), ([8, 7, 2, 3, 4, 5, 6].as_slice(), [].as_slice())); - - // Now that we've adding thing in place of the two that we removed from - // the front of the iterator, we're back to matching the buffer pointer. - assert_eq!(v.as_slices().0.as_ptr(), buf); - assert_eq!(&v[v.len() - 1] as *const _, last); - - v.push_front(9); - assert_eq!(v.as_slices(), ([9].as_slice(), [8, 7, 2, 3, 4, 5, 6].as_slice())); - assert_eq!(v.capacity(), 13); - } -} diff --git a/library/alloc/tests/vec_deque_alloc_error.rs b/library/alloc/tests/vec_deque_alloc_error.rs deleted file mode 100644 index 21a9118a05b..00000000000 --- a/library/alloc/tests/vec_deque_alloc_error.rs +++ /dev/null @@ -1,48 +0,0 @@ -#![feature(alloc_error_hook, allocator_api)] - -use std::alloc::{AllocError, Allocator, Layout, System, set_alloc_error_hook}; -use std::collections::VecDeque; -use std::panic::{AssertUnwindSafe, catch_unwind}; -use std::ptr::NonNull; - -#[test] -#[cfg_attr(not(panic = "unwind"), ignore = "test requires unwinding support")] -fn test_shrink_to_unwind() { - // This tests that `shrink_to` leaves the deque in a consistent state when - // the call to `RawVec::shrink_to_fit` unwinds. The code is adapted from #123369 - // but changed to hopefully not have any UB even if the test fails. - - struct BadAlloc; - - unsafe impl Allocator for BadAlloc { - fn allocate(&self, l: Layout) -> Result<NonNull<[u8]>, AllocError> { - // We allocate zeroed here so that the whole buffer of the deque - // is always initialized. That way, even if the deque is left in - // an inconsistent state, no uninitialized memory should be accessed. - System.allocate_zeroed(l) - } - - unsafe fn deallocate(&self, ptr: NonNull<u8>, layout: Layout) { - unsafe { System.deallocate(ptr, layout) } - } - - unsafe fn shrink( - &self, - _ptr: NonNull<u8>, - _old_layout: Layout, - _new_layout: Layout, - ) -> Result<NonNull<[u8]>, AllocError> { - Err(AllocError) - } - } - - set_alloc_error_hook(|_| panic!("alloc error")); - - let mut v = VecDeque::with_capacity_in(15, BadAlloc); - v.push_back(1); - v.push_front(2); - // This should unwind because it calls `BadAlloc::shrink` and then `handle_alloc_error` which unwinds. - assert!(catch_unwind(AssertUnwindSafe(|| v.shrink_to_fit())).is_err()); - // This should only pass if the deque is left in a consistent state. - assert_eq!(v, [2, 1]); -} |
