diff options
| author | bjorn3 <17426603+bjorn3@users.noreply.github.com> | 2024-12-04 14:26:18 +0000 |
|---|---|---|
| committer | bjorn3 <17426603+bjorn3@users.noreply.github.com> | 2024-12-04 14:32:04 +0000 |
| commit | b440ef8cdf029476d84e6ce8841f1e549d60998f (patch) | |
| tree | 192dbce455a4b09d02f0268f0fb7f35b758a5904 /library/alloc/src | |
| parent | 733616f7236b4be140ce851a30b3bb06532b9364 (diff) | |
| download | rust-b440ef8cdf029476d84e6ce8841f1e549d60998f.tar.gz rust-b440ef8cdf029476d84e6ce8841f1e549d60998f.zip | |
Move some alloc tests to the alloctests crate
Unit tests directly inside of standard library crates require a very fragile way of building that is hard to reproduce outside of bootstrap.
Diffstat (limited to 'library/alloc/src')
| -rw-r--r-- | library/alloc/src/alloc.rs | 3 | ||||
| -rw-r--r-- | library/alloc/src/alloc/tests.rs | 30 | ||||
| -rw-r--r-- | library/alloc/src/collections/binary_heap/mod.rs | 3 | ||||
| -rw-r--r-- | library/alloc/src/collections/binary_heap/tests.rs | 580 | ||||
| -rw-r--r-- | library/alloc/src/ffi/c_str.rs | 3 | ||||
| -rw-r--r-- | library/alloc/src/ffi/c_str/tests.rs | 226 | ||||
| -rw-r--r-- | library/alloc/src/lib.rs | 2 | ||||
| -rw-r--r-- | library/alloc/src/sync.rs | 3 | ||||
| -rw-r--r-- | library/alloc/src/sync/tests.rs | 717 | ||||
| -rw-r--r-- | library/alloc/src/tests.rs | 140 |
10 files changed, 0 insertions, 1707 deletions
diff --git a/library/alloc/src/alloc.rs b/library/alloc/src/alloc.rs index 04b7315e650..ae34fc65326 100644 --- a/library/alloc/src/alloc.rs +++ b/library/alloc/src/alloc.rs @@ -10,9 +10,6 @@ use core::hint; #[cfg(not(test))] use core::ptr::{self, NonNull}; -#[cfg(test)] -mod tests; - extern "Rust" { // These are the magic symbols to call the global allocator. rustc generates // them to call `__rg_alloc` etc. if there is a `#[global_allocator]` attribute diff --git a/library/alloc/src/alloc/tests.rs b/library/alloc/src/alloc/tests.rs deleted file mode 100644 index 5d6077f057a..00000000000 --- a/library/alloc/src/alloc/tests.rs +++ /dev/null @@ -1,30 +0,0 @@ -use super::*; - -extern crate test; -use test::Bencher; - -use crate::boxed::Box; - -#[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/src/collections/binary_heap/mod.rs b/library/alloc/src/collections/binary_heap/mod.rs index 5d3997e14e3..116e0e73e96 100644 --- a/library/alloc/src/collections/binary_heap/mod.rs +++ b/library/alloc/src/collections/binary_heap/mod.rs @@ -155,9 +155,6 @@ use crate::collections::TryReserveError; use crate::slice; use crate::vec::{self, AsVecIntoIter, Vec}; -#[cfg(test)] -mod tests; - /// A priority queue implemented with a binary heap. /// /// This will be a max-heap. diff --git a/library/alloc/src/collections/binary_heap/tests.rs b/library/alloc/src/collections/binary_heap/tests.rs deleted file mode 100644 index ad0a020a1a9..00000000000 --- a/library/alloc/src/collections/binary_heap/tests.rs +++ /dev/null @@ -1,580 +0,0 @@ -use std::panic::{AssertUnwindSafe, catch_unwind}; - -use super::*; -use crate::boxed::Box; -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. -// FIXME: re-enable emscripten once it can unwind again -#[test] -#[cfg(not(target_os = "emscripten"))] -#[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_helpers::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/src/ffi/c_str.rs b/library/alloc/src/ffi/c_str.rs index 9c074383a5e..c7d6d8a55c2 100644 --- a/library/alloc/src/ffi/c_str.rs +++ b/library/alloc/src/ffi/c_str.rs @@ -1,8 +1,5 @@ //! [`CString`] and its related types. -#[cfg(test)] -mod tests; - use core::borrow::Borrow; use core::ffi::{CStr, c_char}; use core::num::NonZero; diff --git a/library/alloc/src/ffi/c_str/tests.rs b/library/alloc/src/ffi/c_str/tests.rs deleted file mode 100644 index d6b797347c2..00000000000 --- a/library/alloc/src/ffi/c_str/tests.rs +++ /dev/null @@ -1,226 +0,0 @@ -use core::assert_matches::assert_matches; -use core::ffi::FromBytesUntilNulError; -#[allow(deprecated)] -use core::hash::SipHasher13 as DefaultHasher; -use core::hash::{Hash, Hasher}; - -use super::*; - -#[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/src/lib.rs b/library/alloc/src/lib.rs index 84f4202c02a..b514cc792ce 100644 --- a/library/alloc/src/lib.rs +++ b/library/alloc/src/lib.rs @@ -238,8 +238,6 @@ pub mod string; pub mod sync; #[cfg(all(not(no_global_oom_handling), not(no_rc), not(no_sync)))] pub mod task; -#[cfg(test)] -mod tests; pub mod vec; #[doc(hidden)] diff --git a/library/alloc/src/sync.rs b/library/alloc/src/sync.rs index b8bdd298c27..6cf41a3fa4e 100644 --- a/library/alloc/src/sync.rs +++ b/library/alloc/src/sync.rs @@ -39,9 +39,6 @@ use crate::string::String; #[cfg(not(no_global_oom_handling))] use crate::vec::Vec; -#[cfg(test)] -mod tests; - /// A soft limit on the amount of references that may be made to an `Arc`. /// /// Going above this limit will abort your program (although not diff --git a/library/alloc/src/sync/tests.rs b/library/alloc/src/sync/tests.rs deleted file mode 100644 index de5816fda97..00000000000 --- a/library/alloc/src/sync/tests.rs +++ /dev/null @@ -1,717 +0,0 @@ -use std::clone::Clone; -use std::mem::MaybeUninit; -use std::option::Option::None; -use std::sync::Mutex; -use std::sync::atomic::AtomicUsize; -use std::sync::atomic::Ordering::SeqCst; -use std::sync::mpsc::channel; -use std::thread; - -use super::*; - -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] -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/src/tests.rs b/library/alloc/src/tests.rs deleted file mode 100644 index b95d11cb07e..00000000000 --- a/library/alloc/src/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()); -} |
