diff options
author | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-05-30 03:59:35 +0000 |
---|---|---|
committer | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-05-30 03:59:35 +0000 |
commit | d1b2d29528b7794b41e66fc2136e395a02f8529b (patch) | |
tree | a4a17504b260206dec3cf55b2dca82929a348ac2 /library/core/tests | |
parent | Releasing progress-linux version 1.72.1+dfsg1-1~progress7.99u1. (diff) | |
download | rustc-d1b2d29528b7794b41e66fc2136e395a02f8529b.tar.xz rustc-d1b2d29528b7794b41e66fc2136e395a02f8529b.zip |
Merging upstream version 1.73.0+dfsg1.
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to 'library/core/tests')
-rw-r--r-- | library/core/tests/any.rs | 62 | ||||
-rw-r--r-- | library/core/tests/error.rs | 66 | ||||
-rw-r--r-- | library/core/tests/iter/adapters/map_windows.rs | 283 | ||||
-rw-r--r-- | library/core/tests/iter/adapters/mod.rs | 1 | ||||
-rw-r--r-- | library/core/tests/iter/traits/iterator.rs | 31 | ||||
-rw-r--r-- | library/core/tests/lib.rs | 7 | ||||
-rw-r--r-- | library/core/tests/manually_drop.rs | 2 | ||||
-rw-r--r-- | library/core/tests/slice.rs | 28 |
8 files changed, 414 insertions, 66 deletions
diff --git a/library/core/tests/any.rs b/library/core/tests/any.rs index a8f6b7ebb..8d2d31b64 100644 --- a/library/core/tests/any.rs +++ b/library/core/tests/any.rs @@ -147,65 +147,3 @@ fn dyn_type_name() { std::any::type_name::<dyn Foo<Bar = i32> + Send + Sync>() ); } - -// Test the `Provider` API. - -struct SomeConcreteType { - some_string: String, -} - -impl Provider for SomeConcreteType { - fn provide<'a>(&'a self, demand: &mut Demand<'a>) { - demand - .provide_ref::<String>(&self.some_string) - .provide_ref::<str>(&self.some_string) - .provide_value_with::<String>(|| "bye".to_owned()); - } -} - -// Test the provide and request mechanisms with a by-reference trait object. -#[test] -fn test_provider() { - let obj: &dyn Provider = &SomeConcreteType { some_string: "hello".to_owned() }; - - assert_eq!(&**request_ref::<String>(obj).unwrap(), "hello"); - assert_eq!(&*request_value::<String>(obj).unwrap(), "bye"); - assert_eq!(request_value::<u8>(obj), None); -} - -// Test the provide and request mechanisms with a boxed trait object. -#[test] -fn test_provider_boxed() { - let obj: Box<dyn Provider> = Box::new(SomeConcreteType { some_string: "hello".to_owned() }); - - assert_eq!(&**request_ref::<String>(&*obj).unwrap(), "hello"); - assert_eq!(&*request_value::<String>(&*obj).unwrap(), "bye"); - assert_eq!(request_value::<u8>(&*obj), None); -} - -// Test the provide and request mechanisms with a concrete object. -#[test] -fn test_provider_concrete() { - let obj = SomeConcreteType { some_string: "hello".to_owned() }; - - assert_eq!(&**request_ref::<String>(&obj).unwrap(), "hello"); - assert_eq!(&*request_value::<String>(&obj).unwrap(), "bye"); - assert_eq!(request_value::<u8>(&obj), None); -} - -trait OtherTrait: Provider {} - -impl OtherTrait for SomeConcreteType {} - -impl dyn OtherTrait { - fn get_ref<T: 'static + ?Sized>(&self) -> Option<&T> { - request_ref::<T>(self) - } -} - -// Test the provide and request mechanisms via an intermediate trait. -#[test] -fn test_provider_intermediate() { - let obj: &dyn OtherTrait = &SomeConcreteType { some_string: "hello".to_owned() }; - assert_eq!(obj.get_ref::<str>().unwrap(), "hello"); -} diff --git a/library/core/tests/error.rs b/library/core/tests/error.rs new file mode 100644 index 000000000..cb7cb5441 --- /dev/null +++ b/library/core/tests/error.rs @@ -0,0 +1,66 @@ +use core::error::{request_value, request_ref, Request}; + +// Test the `Request` API. +#[derive(Debug)] +struct SomeConcreteType { + some_string: String, +} + +impl std::fmt::Display for SomeConcreteType { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + write!(f, "A") + } +} + +impl std::error::Error for SomeConcreteType { + fn provide<'a>(&'a self, request: &mut Request<'a>) { + request + .provide_ref::<String>(&self.some_string) + .provide_ref::<str>(&self.some_string) + .provide_value_with::<String>(|| "bye".to_owned()); + } +} + +// Test the Error.provide and request mechanisms with a by-reference trait object. +#[test] +fn test_error_generic_member_access() { + let obj = &SomeConcreteType { some_string: "hello".to_owned() }; + + assert_eq!(request_ref::<String>(&*obj).unwrap(), "hello"); + assert_eq!(request_value::<String>(&*obj).unwrap(), "bye"); + assert_eq!(request_value::<u8>(&obj), None); +} + +// Test the Error.provide and request mechanisms with a by-reference trait object. +#[test] +fn test_request_constructor() { + let obj: &dyn std::error::Error = &SomeConcreteType { some_string: "hello".to_owned() }; + + assert_eq!(request_ref::<String>(&*obj).unwrap(), "hello"); + assert_eq!(request_value::<String>(&*obj).unwrap(), "bye"); + assert_eq!(request_value::<u8>(&obj), None); +} + +// Test the Error.provide and request mechanisms with a boxed trait object. +#[test] +fn test_error_generic_member_access_boxed() { + let obj: Box<dyn std::error::Error> = + Box::new(SomeConcreteType { some_string: "hello".to_owned() }); + + assert_eq!(request_ref::<String>(&*obj).unwrap(), "hello"); + assert_eq!(request_value::<String>(&*obj).unwrap(), "bye"); + + // NOTE: Box<E> only implements Error when E: Error + Sized, which means we can't pass a + // Box<dyn Error> to request_value. + //assert_eq!(request_value::<String>(&obj).unwrap(), "bye"); +} + +// Test the Error.provide and request mechanisms with a concrete object. +#[test] +fn test_error_generic_member_access_concrete() { + let obj = SomeConcreteType { some_string: "hello".to_owned() }; + + assert_eq!(request_ref::<String>(&obj).unwrap(), "hello"); + assert_eq!(request_value::<String>(&obj).unwrap(), "bye"); + assert_eq!(request_value::<u8>(&obj), None); +} diff --git a/library/core/tests/iter/adapters/map_windows.rs b/library/core/tests/iter/adapters/map_windows.rs new file mode 100644 index 000000000..7fb2408f8 --- /dev/null +++ b/library/core/tests/iter/adapters/map_windows.rs @@ -0,0 +1,283 @@ +use std::sync::atomic::{AtomicUsize, Ordering::SeqCst}; + +#[cfg(not(panic = "abort"))] +mod drop_checks { + //! These tests mainly make sure the elements are correctly dropped. + use std::sync::atomic::{AtomicBool, AtomicUsize, Ordering::SeqCst}; + + #[derive(Debug)] + struct DropInfo { + dropped_twice: AtomicBool, + alive_count: AtomicUsize, + } + + impl DropInfo { + const fn new() -> Self { + Self { dropped_twice: AtomicBool::new(false), alive_count: AtomicUsize::new(0) } + } + + #[track_caller] + fn check(&self) { + assert!(!self.dropped_twice.load(SeqCst), "a value was dropped twice"); + assert_eq!(self.alive_count.load(SeqCst), 0); + } + } + + #[derive(Debug)] + struct DropCheck<'a> { + info: &'a DropInfo, + was_dropped: bool, + } + + impl<'a> DropCheck<'a> { + fn new(info: &'a DropInfo) -> Self { + info.alive_count.fetch_add(1, SeqCst); + + Self { info, was_dropped: false } + } + } + + impl Drop for DropCheck<'_> { + fn drop(&mut self) { + if self.was_dropped { + self.info.dropped_twice.store(true, SeqCst); + } + self.was_dropped = true; + + self.info.alive_count.fetch_sub(1, SeqCst); + } + } + + fn iter(info: &DropInfo, len: usize, panic_at: usize) -> impl Iterator<Item = DropCheck<'_>> { + (0..len).map(move |i| { + if i == panic_at { + panic!("intended panic"); + } + DropCheck::new(info) + }) + } + + #[track_caller] + fn check<const N: usize>(len: usize, panic_at: usize) { + check_drops(|info| { + iter(info, len, panic_at).map_windows(|_: &[_; N]| {}).last(); + }); + } + + #[track_caller] + fn check_drops(f: impl FnOnce(&DropInfo)) { + let info = DropInfo::new(); + let _ = std::panic::catch_unwind(std::panic::AssertUnwindSafe(|| { + f(&info); + })); + info.check(); + } + + #[test] + fn no_iter_panic_n1() { + check::<1>(0, 100); + check::<1>(1, 100); + check::<1>(2, 100); + check::<1>(13, 100); + } + + #[test] + fn no_iter_panic_n2() { + check::<2>(0, 100); + check::<2>(1, 100); + check::<2>(2, 100); + check::<2>(3, 100); + check::<2>(13, 100); + } + + #[test] + fn no_iter_panic_n5() { + check::<5>(0, 100); + check::<5>(1, 100); + check::<5>(2, 100); + check::<5>(13, 100); + check::<5>(30, 100); + } + + #[test] + fn panic_in_first_batch() { + check::<1>(7, 0); + + check::<2>(7, 0); + check::<2>(7, 1); + + check::<3>(7, 0); + check::<3>(7, 1); + check::<3>(7, 2); + } + + #[test] + fn panic_in_middle() { + check::<1>(7, 1); + check::<1>(7, 5); + check::<1>(7, 6); + + check::<2>(7, 2); + check::<2>(7, 5); + check::<2>(7, 6); + + check::<5>(13, 5); + check::<5>(13, 8); + check::<5>(13, 12); + } + + #[test] + fn len_equals_n() { + check::<1>(1, 100); + check::<1>(1, 0); + + check::<2>(2, 100); + check::<2>(2, 0); + check::<2>(2, 1); + + check::<5>(5, 100); + check::<5>(5, 0); + check::<5>(5, 1); + check::<5>(5, 4); + } +} + +#[test] +fn output_n1() { + assert_eq!("".chars().map_windows(|[c]| *c).collect::<Vec<_>>(), vec![]); + assert_eq!("x".chars().map_windows(|[c]| *c).collect::<Vec<_>>(), vec!['x']); + assert_eq!("abcd".chars().map_windows(|[c]| *c).collect::<Vec<_>>(), vec!['a', 'b', 'c', 'd']); +} + +#[test] +fn output_n2() { + assert_eq!( + "".chars().map_windows(|a: &[_; 2]| *a).collect::<Vec<_>>(), + <Vec<[char; 2]>>::new(), + ); + assert_eq!("ab".chars().map_windows(|a: &[_; 2]| *a).collect::<Vec<_>>(), vec![['a', 'b']]); + assert_eq!( + "abcd".chars().map_windows(|a: &[_; 2]| *a).collect::<Vec<_>>(), + vec![['a', 'b'], ['b', 'c'], ['c', 'd']], + ); +} + +#[test] +fn test_case_from_pr_82413_comment() { + for () in std::iter::repeat("0".to_owned()).map_windows(|_: &[_; 3]| {}).take(4) {} +} + +#[test] +#[should_panic = "array in `Iterator::map_windows` must contain more than 0 elements"] +fn check_zero_window() { + let _ = std::iter::repeat(0).map_windows(|_: &[_; 0]| ()); +} + +#[test] +fn test_zero_sized_type() { + #[derive(Copy, Clone, Debug, Eq, PartialEq)] + struct Data; + let data: Vec<_> = + std::iter::repeat(Data).take(10).map_windows(|arr: &[Data; 5]| *arr).collect(); + assert_eq!(data, [[Data; 5]; 6]); +} + +#[test] +#[should_panic = "array size of `Iterator::map_windows` is too large"] +fn test_too_large_array_size() { + let _ = std::iter::repeat(()).map_windows(|arr: &[(); usize::MAX]| *arr); +} + +#[test] +fn test_laziness() { + let counter = AtomicUsize::new(0); + let mut iter = (0..5) + .inspect(|_| { + counter.fetch_add(1, SeqCst); + }) + .map_windows(|arr: &[i32; 2]| *arr); + assert_eq!(counter.load(SeqCst), 0); + + assert_eq!(iter.next(), Some([0, 1])); + // The first iteration consumes N items (N = 2). + assert_eq!(counter.load(SeqCst), 2); + + assert_eq!(iter.next(), Some([1, 2])); + assert_eq!(counter.load(SeqCst), 3); + + assert_eq!(iter.next(), Some([2, 3])); + assert_eq!(counter.load(SeqCst), 4); + + assert_eq!(iter.next(), Some([3, 4])); + assert_eq!(counter.load(SeqCst), 5); + + assert_eq!(iter.next(), None); + assert_eq!(counter.load(SeqCst), 5); +} + +#[test] +fn test_size_hint() { + struct SizeHintCheckHelper((usize, Option<usize>)); + + impl Iterator for SizeHintCheckHelper { + type Item = i32; + + fn next(&mut self) -> Option<i32> { + let (ref mut lo, ref mut hi) = self.0; + let next = (*hi != Some(0)).then_some(0); + *lo = lo.saturating_sub(1); + if let Some(hi) = hi { + *hi = hi.saturating_sub(1); + } + next + } + + fn size_hint(&self) -> (usize, Option<usize>) { + self.0 + } + } + + fn check_size_hint<const N: usize>( + size_hint: (usize, Option<usize>), + mut mapped_size_hint: (usize, Option<usize>), + ) { + let mut iter = SizeHintCheckHelper(size_hint); + let mut mapped_iter = iter.by_ref().map_windows(|_: &[_; N]| ()); + while mapped_iter.size_hint().0 > 0 { + assert_eq!(mapped_iter.size_hint(), mapped_size_hint); + assert!(mapped_iter.next().is_some()); + mapped_size_hint.0 -= 1; + mapped_size_hint.1 = mapped_size_hint.1.map(|hi| hi.saturating_sub(1)); + } + } + + check_size_hint::<1>((0, None), (0, None)); + check_size_hint::<1>((0, Some(0)), (0, Some(0))); + check_size_hint::<1>((0, Some(2)), (0, Some(2))); + check_size_hint::<1>((1, None), (1, None)); + check_size_hint::<1>((1, Some(1)), (1, Some(1))); + check_size_hint::<1>((1, Some(4)), (1, Some(4))); + check_size_hint::<1>((5, None), (5, None)); + check_size_hint::<1>((5, Some(5)), (5, Some(5))); + check_size_hint::<1>((5, Some(10)), (5, Some(10))); + + check_size_hint::<2>((0, None), (0, None)); + check_size_hint::<2>((0, Some(0)), (0, Some(0))); + check_size_hint::<2>((0, Some(2)), (0, Some(1))); + check_size_hint::<2>((1, None), (0, None)); + check_size_hint::<2>((1, Some(1)), (0, Some(0))); + check_size_hint::<2>((1, Some(4)), (0, Some(3))); + check_size_hint::<2>((5, None), (4, None)); + check_size_hint::<2>((5, Some(5)), (4, Some(4))); + check_size_hint::<2>((5, Some(10)), (4, Some(9))); + + check_size_hint::<5>((0, None), (0, None)); + check_size_hint::<5>((0, Some(0)), (0, Some(0))); + check_size_hint::<5>((0, Some(2)), (0, Some(0))); + check_size_hint::<5>((1, None), (0, None)); + check_size_hint::<5>((1, Some(1)), (0, Some(0))); + check_size_hint::<5>((1, Some(4)), (0, Some(0))); + check_size_hint::<5>((5, None), (1, None)); + check_size_hint::<5>((5, Some(5)), (1, Some(1))); + check_size_hint::<5>((5, Some(10)), (1, Some(6))); +} diff --git a/library/core/tests/iter/adapters/mod.rs b/library/core/tests/iter/adapters/mod.rs index ca3463aa7..dedb4c0a9 100644 --- a/library/core/tests/iter/adapters/mod.rs +++ b/library/core/tests/iter/adapters/mod.rs @@ -13,6 +13,7 @@ mod fuse; mod inspect; mod intersperse; mod map; +mod map_windows; mod peekable; mod scan; mod skip; diff --git a/library/core/tests/iter/traits/iterator.rs b/library/core/tests/iter/traits/iterator.rs index 9eebfb1f1..995bbf0e2 100644 --- a/library/core/tests/iter/traits/iterator.rs +++ b/library/core/tests/iter/traits/iterator.rs @@ -1,3 +1,4 @@ +use core::cmp::Ordering; use core::num::NonZeroUsize; /// A wrapper struct that implements `Eq` and `Ord` based on the wrapped @@ -371,11 +372,39 @@ fn test_by_ref() { #[test] fn test_is_sorted() { + // Tests on integers assert!([1, 2, 2, 9].iter().is_sorted()); assert!(![1, 3, 2].iter().is_sorted()); assert!([0].iter().is_sorted()); - assert!(std::iter::empty::<i32>().is_sorted()); + assert!([0, 0].iter().is_sorted()); + assert!(core::iter::empty::<i32>().is_sorted()); + + // Tests on floats + assert!([1.0f32, 2.0, 2.0, 9.0].iter().is_sorted()); + assert!(![1.0f32, 3.0f32, 2.0f32].iter().is_sorted()); + assert!([0.0f32].iter().is_sorted()); + assert!([0.0f32, 0.0f32].iter().is_sorted()); + // Test cases with NaNs + assert!([f32::NAN].iter().is_sorted()); + assert!(![f32::NAN, f32::NAN].iter().is_sorted()); assert!(![0.0, 1.0, f32::NAN].iter().is_sorted()); + // Tests from <https://github.com/rust-lang/rust/pull/55045#discussion_r229689884> + assert!(![f32::NAN, f32::NAN, f32::NAN].iter().is_sorted()); + assert!(![1.0, f32::NAN, 2.0].iter().is_sorted()); + assert!(![2.0, f32::NAN, 1.0].iter().is_sorted()); + assert!(![2.0, f32::NAN, 1.0, 7.0].iter().is_sorted()); + assert!(![2.0, f32::NAN, 1.0, 0.0].iter().is_sorted()); + assert!(![-f32::NAN, -1.0, 0.0, 1.0, f32::NAN].iter().is_sorted()); + assert!(![f32::NAN, -f32::NAN, -1.0, 0.0, 1.0].iter().is_sorted()); + assert!(![1.0, f32::NAN, -f32::NAN, -1.0, 0.0].iter().is_sorted()); + assert!(![0.0, 1.0, f32::NAN, -f32::NAN, -1.0].iter().is_sorted()); + assert!(![-1.0, 0.0, 1.0, f32::NAN, -f32::NAN].iter().is_sorted()); + + // Tests for is_sorted_by + assert!(![6, 2, 8, 5, 1, -60, 1337].iter().is_sorted()); + assert!([6, 2, 8, 5, 1, -60, 1337].iter().is_sorted_by(|_, _| Some(Ordering::Less))); + + // Tests for is_sorted_by_key assert!([-2, -1, 0, 3].iter().is_sorted()); assert!(![-2i32, -1, 0, 3].iter().is_sorted_by_key(|n| n.abs())); assert!(!["c", "bb", "aaa"].iter().is_sorted()); diff --git a/library/core/tests/lib.rs b/library/core/tests/lib.rs index 3e6d31fcd..7a6def37a 100644 --- a/library/core/tests/lib.rs +++ b/library/core/tests/lib.rs @@ -93,7 +93,7 @@ #![feature(const_option)] #![feature(const_option_ext)] #![feature(const_result)] -#![feature(integer_atomics)] +#![cfg_attr(target_has_atomic = "128", feature(integer_atomics))] #![feature(int_roundings)] #![feature(slice_group_by)] #![feature(split_array)] @@ -105,11 +105,14 @@ #![feature(const_slice_from_ref)] #![feature(waker_getters)] #![feature(slice_flatten)] -#![feature(provide_any)] +#![feature(error_generic_member_access)] +#![feature(error_in_core)] +#![feature(trait_upcasting)] #![feature(utf8_chunks)] #![feature(is_ascii_octdigit)] #![feature(get_many_mut)] #![feature(offset_of)] +#![feature(iter_map_windows)] #![deny(unsafe_op_in_unsafe_fn)] #![deny(fuzzy_provenance_casts)] diff --git a/library/core/tests/manually_drop.rs b/library/core/tests/manually_drop.rs index 22d72d219..bbf444471 100644 --- a/library/core/tests/manually_drop.rs +++ b/library/core/tests/manually_drop.rs @@ -1,4 +1,4 @@ -#![cfg_attr(not(bootstrap), allow(undropped_manually_drops))] +#![allow(undropped_manually_drops)] use core::mem::ManuallyDrop; diff --git a/library/core/tests/slice.rs b/library/core/tests/slice.rs index 88f54591b..865e702b5 100644 --- a/library/core/tests/slice.rs +++ b/library/core/tests/slice.rs @@ -2278,11 +2278,39 @@ fn test_copy_within_panics_src_out_of_bounds() { fn test_is_sorted() { let empty: [i32; 0] = []; + // Tests on integers assert!([1, 2, 2, 9].is_sorted()); assert!(![1, 3, 2].is_sorted()); assert!([0].is_sorted()); + assert!([0, 0].is_sorted()); assert!(empty.is_sorted()); + + // Tests on floats + assert!([1.0f32, 2.0, 2.0, 9.0].is_sorted()); + assert!(![1.0f32, 3.0f32, 2.0f32].is_sorted()); + assert!([0.0f32].is_sorted()); + assert!([0.0f32, 0.0f32].is_sorted()); + // Test cases with NaNs + assert!([f32::NAN].is_sorted()); + assert!(![f32::NAN, f32::NAN].is_sorted()); assert!(![0.0, 1.0, f32::NAN].is_sorted()); + // Tests from <https://github.com/rust-lang/rust/pull/55045#discussion_r229689884> + assert!(![f32::NAN, f32::NAN, f32::NAN].is_sorted()); + assert!(![1.0, f32::NAN, 2.0].is_sorted()); + assert!(![2.0, f32::NAN, 1.0].is_sorted()); + assert!(![2.0, f32::NAN, 1.0, 7.0].is_sorted()); + assert!(![2.0, f32::NAN, 1.0, 0.0].is_sorted()); + assert!(![-f32::NAN, -1.0, 0.0, 1.0, f32::NAN].is_sorted()); + assert!(![f32::NAN, -f32::NAN, -1.0, 0.0, 1.0].is_sorted()); + assert!(![1.0, f32::NAN, -f32::NAN, -1.0, 0.0].is_sorted()); + assert!(![0.0, 1.0, f32::NAN, -f32::NAN, -1.0].is_sorted()); + assert!(![-1.0, 0.0, 1.0, f32::NAN, -f32::NAN].is_sorted()); + + // Tests for is_sorted_by + assert!(![6, 2, 8, 5, 1, -60, 1337].is_sorted()); + assert!([6, 2, 8, 5, 1, -60, 1337].is_sorted_by(|_, _| Some(Ordering::Less))); + + // Tests for is_sorted_by_key assert!([-2, -1, 0, 3].is_sorted()); assert!(![-2i32, -1, 0, 3].is_sorted_by_key(|n| n.abs())); assert!(!["c", "bb", "aaa"].is_sorted()); |