summaryrefslogtreecommitdiffstats
path: root/library/core/tests/iter/adapters/step_by.rs
diff options
context:
space:
mode:
Diffstat (limited to 'library/core/tests/iter/adapters/step_by.rs')
-rw-r--r--library/core/tests/iter/adapters/step_by.rs246
1 files changed, 246 insertions, 0 deletions
diff --git a/library/core/tests/iter/adapters/step_by.rs b/library/core/tests/iter/adapters/step_by.rs
new file mode 100644
index 000000000..94f2fa8c2
--- /dev/null
+++ b/library/core/tests/iter/adapters/step_by.rs
@@ -0,0 +1,246 @@
+use core::iter::*;
+
+#[test]
+fn test_iterator_step_by() {
+ // Identity
+ let mut it = (0..).step_by(1).take(3);
+ assert_eq!(it.next(), Some(0));
+ assert_eq!(it.next(), Some(1));
+ assert_eq!(it.next(), Some(2));
+ assert_eq!(it.next(), None);
+
+ let mut it = (0..).step_by(3).take(4);
+ assert_eq!(it.next(), Some(0));
+ assert_eq!(it.next(), Some(3));
+ assert_eq!(it.next(), Some(6));
+ assert_eq!(it.next(), Some(9));
+ assert_eq!(it.next(), None);
+
+ let mut it = (0..3).step_by(1);
+ assert_eq!(it.next_back(), Some(2));
+ assert_eq!(it.next_back(), Some(1));
+ assert_eq!(it.next_back(), Some(0));
+ assert_eq!(it.next_back(), None);
+
+ let mut it = (0..11).step_by(3);
+ assert_eq!(it.next_back(), Some(9));
+ assert_eq!(it.next_back(), Some(6));
+ assert_eq!(it.next_back(), Some(3));
+ assert_eq!(it.next_back(), Some(0));
+ assert_eq!(it.next_back(), None);
+}
+
+#[test]
+fn test_iterator_step_by_nth() {
+ let mut it = (0..16).step_by(5);
+ assert_eq!(it.nth(0), Some(0));
+ assert_eq!(it.nth(0), Some(5));
+ assert_eq!(it.nth(0), Some(10));
+ assert_eq!(it.nth(0), Some(15));
+ assert_eq!(it.nth(0), None);
+
+ let it = (0..18).step_by(5);
+ assert_eq!(it.clone().nth(0), Some(0));
+ assert_eq!(it.clone().nth(1), Some(5));
+ assert_eq!(it.clone().nth(2), Some(10));
+ assert_eq!(it.clone().nth(3), Some(15));
+ assert_eq!(it.clone().nth(4), None);
+ assert_eq!(it.clone().nth(42), None);
+}
+
+#[test]
+fn test_iterator_step_by_nth_overflow() {
+ #[cfg(target_pointer_width = "16")]
+ type Bigger = u32;
+ #[cfg(target_pointer_width = "32")]
+ type Bigger = u64;
+ #[cfg(target_pointer_width = "64")]
+ type Bigger = u128;
+
+ #[derive(Clone)]
+ struct Test(Bigger);
+ impl Iterator for &mut Test {
+ type Item = i32;
+ fn next(&mut self) -> Option<Self::Item> {
+ Some(21)
+ }
+ fn nth(&mut self, n: usize) -> Option<Self::Item> {
+ self.0 += n as Bigger + 1;
+ Some(42)
+ }
+ }
+
+ let mut it = Test(0);
+ let root = usize::MAX >> (usize::BITS / 2);
+ let n = root + 20;
+ (&mut it).step_by(n).nth(n);
+ assert_eq!(it.0, n as Bigger * n as Bigger);
+
+ // large step
+ let mut it = Test(0);
+ (&mut it).step_by(usize::MAX).nth(5);
+ assert_eq!(it.0, (usize::MAX as Bigger) * 5);
+
+ // n + 1 overflows
+ let mut it = Test(0);
+ (&mut it).step_by(2).nth(usize::MAX);
+ assert_eq!(it.0, (usize::MAX as Bigger) * 2);
+
+ // n + 1 overflows
+ let mut it = Test(0);
+ (&mut it).step_by(1).nth(usize::MAX);
+ assert_eq!(it.0, (usize::MAX as Bigger) * 1);
+}
+
+#[test]
+fn test_iterator_step_by_nth_try_fold() {
+ let mut it = (0..).step_by(10);
+ assert_eq!(it.try_fold(0, i8::checked_add), None);
+ assert_eq!(it.next(), Some(60));
+ assert_eq!(it.try_fold(0, i8::checked_add), None);
+ assert_eq!(it.next(), Some(90));
+
+ let mut it = (100..).step_by(10);
+ assert_eq!(it.try_fold(50, i8::checked_add), None);
+ assert_eq!(it.next(), Some(110));
+
+ let mut it = (100..=100).step_by(10);
+ assert_eq!(it.next(), Some(100));
+ assert_eq!(it.try_fold(0, i8::checked_add), Some(0));
+}
+
+#[test]
+fn test_iterator_step_by_nth_back() {
+ let mut it = (0..16).step_by(5);
+ assert_eq!(it.nth_back(0), Some(15));
+ assert_eq!(it.nth_back(0), Some(10));
+ assert_eq!(it.nth_back(0), Some(5));
+ assert_eq!(it.nth_back(0), Some(0));
+ assert_eq!(it.nth_back(0), None);
+
+ let mut it = (0..16).step_by(5);
+ assert_eq!(it.next(), Some(0)); // to set `first_take` to `false`
+ assert_eq!(it.nth_back(0), Some(15));
+ assert_eq!(it.nth_back(0), Some(10));
+ assert_eq!(it.nth_back(0), Some(5));
+ assert_eq!(it.nth_back(0), None);
+
+ let it = || (0..18).step_by(5);
+ assert_eq!(it().nth_back(0), Some(15));
+ assert_eq!(it().nth_back(1), Some(10));
+ assert_eq!(it().nth_back(2), Some(5));
+ assert_eq!(it().nth_back(3), Some(0));
+ assert_eq!(it().nth_back(4), None);
+ assert_eq!(it().nth_back(42), None);
+}
+
+#[test]
+fn test_iterator_step_by_nth_try_rfold() {
+ let mut it = (0..100).step_by(10);
+ assert_eq!(it.try_rfold(0, i8::checked_add), None);
+ assert_eq!(it.next_back(), Some(70));
+ assert_eq!(it.next(), Some(0));
+ assert_eq!(it.try_rfold(0, i8::checked_add), None);
+ assert_eq!(it.next_back(), Some(30));
+
+ let mut it = (0..100).step_by(10);
+ assert_eq!(it.try_rfold(50, i8::checked_add), None);
+ assert_eq!(it.next_back(), Some(80));
+
+ let mut it = (100..=100).step_by(10);
+ assert_eq!(it.next_back(), Some(100));
+ assert_eq!(it.try_fold(0, i8::checked_add), Some(0));
+}
+
+#[test]
+#[should_panic]
+fn test_iterator_step_by_zero() {
+ let mut it = (0..).step_by(0);
+ it.next();
+}
+
+#[test]
+fn test_iterator_step_by_size_hint() {
+ struct StubSizeHint(usize, Option<usize>);
+ impl Iterator for StubSizeHint {
+ type Item = ();
+ fn next(&mut self) -> Option<()> {
+ self.0 -= 1;
+ if let Some(ref mut upper) = self.1 {
+ *upper -= 1;
+ }
+ Some(())
+ }
+ fn size_hint(&self) -> (usize, Option<usize>) {
+ (self.0, self.1)
+ }
+ }
+
+ // The two checks in each case are needed because the logic
+ // is different before the first call to `next()`.
+
+ let mut it = StubSizeHint(10, Some(10)).step_by(1);
+ assert_eq!(it.size_hint(), (10, Some(10)));
+ it.next();
+ assert_eq!(it.size_hint(), (9, Some(9)));
+
+ // exact multiple
+ let mut it = StubSizeHint(10, Some(10)).step_by(3);
+ assert_eq!(it.size_hint(), (4, Some(4)));
+ it.next();
+ assert_eq!(it.size_hint(), (3, Some(3)));
+
+ // larger base range, but not enough to get another element
+ let mut it = StubSizeHint(12, Some(12)).step_by(3);
+ assert_eq!(it.size_hint(), (4, Some(4)));
+ it.next();
+ assert_eq!(it.size_hint(), (3, Some(3)));
+
+ // smaller base range, so fewer resulting elements
+ let mut it = StubSizeHint(9, Some(9)).step_by(3);
+ assert_eq!(it.size_hint(), (3, Some(3)));
+ it.next();
+ assert_eq!(it.size_hint(), (2, Some(2)));
+
+ // infinite upper bound
+ let mut it = StubSizeHint(usize::MAX, None).step_by(1);
+ assert_eq!(it.size_hint(), (usize::MAX, None));
+ it.next();
+ assert_eq!(it.size_hint(), (usize::MAX - 1, None));
+
+ // still infinite with larger step
+ let mut it = StubSizeHint(7, None).step_by(3);
+ assert_eq!(it.size_hint(), (3, None));
+ it.next();
+ assert_eq!(it.size_hint(), (2, None));
+
+ // propagates ExactSizeIterator
+ let a = [1, 2, 3, 4, 5];
+ let it = a.iter().step_by(2);
+ assert_eq!(it.len(), 3);
+
+ // Cannot be TrustedLen as a step greater than one makes an iterator
+ // with (usize::MAX, None) no longer meet the safety requirements
+ trait TrustedLenCheck {
+ fn test(self) -> bool;
+ }
+ impl<T: Iterator> TrustedLenCheck for T {
+ default fn test(self) -> bool {
+ false
+ }
+ }
+ impl<T: TrustedLen> TrustedLenCheck for T {
+ fn test(self) -> bool {
+ true
+ }
+ }
+ assert!(TrustedLenCheck::test(a.iter()));
+ assert!(!TrustedLenCheck::test(a.iter().step_by(1)));
+}
+
+#[test]
+fn test_step_by_skip() {
+ assert_eq!((0..640).step_by(128).skip(1).collect::<Vec<_>>(), [128, 256, 384, 512]);
+ assert_eq!((0..=50).step_by(10).nth(3), Some(30));
+ assert_eq!((200..=255u8).step_by(10).nth(3), Some(230));
+}