Skip to content

Commit 5f1aad2

Browse files
committed
Add a bunch of tests for try_fold and try_rfold
1 parent 2f94725 commit 5f1aad2

File tree

3 files changed

+241
-0
lines changed

3 files changed

+241
-0
lines changed

src/libcore/tests/iter.rs

Lines changed: 223 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -664,6 +664,7 @@ fn test_iterator_skip_last() {
664664
fn test_iterator_skip_fold() {
665665
let xs = [0, 1, 2, 3, 5, 13, 15, 16, 17, 19, 20, 30];
666666
let ys = [13, 15, 16, 17, 19, 20, 30];
667+
667668
let it = xs.iter().skip(5);
668669
let i = it.fold(0, |i, &x| {
669670
assert_eq!(x, ys[i]);
@@ -678,6 +679,24 @@ fn test_iterator_skip_fold() {
678679
i + 1
679680
});
680681
assert_eq!(i, ys.len());
682+
683+
let it = xs.iter().skip(5);
684+
let i = it.rfold(ys.len(), |i, &x| {
685+
let i = i - 1;
686+
assert_eq!(x, ys[i]);
687+
i
688+
});
689+
assert_eq!(i, 0);
690+
691+
let mut it = xs.iter().skip(5);
692+
assert_eq!(it.next(), Some(&ys[0])); // process skips before folding
693+
let i = it.rfold(ys.len(), |i, &x| {
694+
let i = i - 1;
695+
assert_eq!(x, ys[i]);
696+
i
697+
});
698+
assert_eq!(i, 1);
699+
681700
}
682701

683702
#[test]
@@ -1478,3 +1497,207 @@ fn test_step_replace_no_between() {
14781497
assert_eq!(x, 1);
14791498
assert_eq!(y, 5);
14801499
}
1500+
1501+
#[test]
1502+
fn test_rev_try_folds() {
1503+
let f = &|acc, x| i32::checked_add(2*acc, x);
1504+
assert_eq!((1..10).rev().try_fold(7, f), (1..10).try_rfold(7, f));
1505+
assert_eq!((1..10).rev().try_rfold(7, f), (1..10).try_fold(7, f));
1506+
1507+
let a = [10, 20, 30, 40, 100, 60, 70, 80, 90];
1508+
let mut iter = a.iter().rev();
1509+
assert_eq!(iter.try_fold(0_i8, |acc, &x| acc.checked_add(x)), None);
1510+
assert_eq!(iter.next(), Some(&70));
1511+
let mut iter = a.iter().rev();
1512+
assert_eq!(iter.try_rfold(0_i8, |acc, &x| acc.checked_add(x)), None);
1513+
assert_eq!(iter.next_back(), Some(&60));
1514+
}
1515+
1516+
#[test]
1517+
fn test_cloned_try_folds() {
1518+
let a = [1, 2, 3, 4, 5, 6, 7, 8, 9];
1519+
let f = &|acc, x| i32::checked_add(2*acc, x);
1520+
let f_ref = &|acc, &x| i32::checked_add(2*acc, x);
1521+
assert_eq!(a.iter().cloned().try_fold(7, f), a.iter().try_fold(7, f_ref));
1522+
assert_eq!(a.iter().cloned().try_rfold(7, f), a.iter().try_rfold(7, f_ref));
1523+
1524+
let a = [10, 20, 30, 40, 100, 60, 70, 80, 90];
1525+
let mut iter = a.iter().cloned();
1526+
assert_eq!(iter.try_fold(0_i8, |acc, x| acc.checked_add(x)), None);
1527+
assert_eq!(iter.next(), Some(60));
1528+
let mut iter = a.iter().cloned();
1529+
assert_eq!(iter.try_rfold(0_i8, |acc, x| acc.checked_add(x)), None);
1530+
assert_eq!(iter.next_back(), Some(70));
1531+
}
1532+
1533+
#[test]
1534+
fn test_chain_try_folds() {
1535+
let c = || (0..10).chain(10..20);
1536+
1537+
let f = &|acc, x| i32::checked_add(2*acc, x);
1538+
assert_eq!(c().try_fold(7, f), (0..20).try_fold(7, f));
1539+
assert_eq!(c().try_rfold(7, f), (0..20).rev().try_fold(7, f));
1540+
1541+
let mut iter = c();
1542+
assert_eq!(iter.position(|x| x == 5), Some(5));
1543+
assert_eq!(iter.next(), Some(6), "stopped in front, state Both");
1544+
assert_eq!(iter.position(|x| x == 13), Some(6));
1545+
assert_eq!(iter.next(), Some(14), "stopped in back, state Back");
1546+
assert_eq!(iter.try_fold(0, |acc, x| Some(acc+x)), Some((15..20).sum()));
1547+
1548+
let mut iter = c().rev(); // use rev to access try_rfold
1549+
assert_eq!(iter.position(|x| x == 15), Some(4));
1550+
assert_eq!(iter.next(), Some(14), "stopped in back, state Both");
1551+
assert_eq!(iter.position(|x| x == 5), Some(8));
1552+
assert_eq!(iter.next(), Some(4), "stopped in front, state Front");
1553+
assert_eq!(iter.try_fold(0, |acc, x| Some(acc+x)), Some((0..4).sum()));
1554+
1555+
let mut iter = c();
1556+
iter.by_ref().rev().nth(14); // skip the last 15, ending in state Front
1557+
assert_eq!(iter.try_fold(7, f), (0..5).try_fold(7, f));
1558+
1559+
let mut iter = c();
1560+
iter.nth(14); // skip the first 15, ending in state Back
1561+
assert_eq!(iter.try_rfold(7, f), (15..20).try_rfold(7, f));
1562+
}
1563+
1564+
#[test]
1565+
fn test_map_try_folds() {
1566+
let f = &|acc, x| i32::checked_add(2*acc, x);
1567+
assert_eq!((0..10).map(|x| x+3).try_fold(7, f), (3..13).try_fold(7, f));
1568+
assert_eq!((0..10).map(|x| x+3).try_rfold(7, f), (3..13).try_rfold(7, f));
1569+
1570+
let mut iter = (0..40).map(|x| x+10);
1571+
assert_eq!(iter.try_fold(0, i8::checked_add), None);
1572+
assert_eq!(iter.next(), Some(20));
1573+
assert_eq!(iter.try_rfold(0, i8::checked_add), None);
1574+
assert_eq!(iter.next_back(), Some(46));
1575+
}
1576+
1577+
#[test]
1578+
fn test_filter_try_folds() {
1579+
fn p(&x: &i32) -> bool { 0 <= x && x < 10 }
1580+
let f = &|acc, x| i32::checked_add(2*acc, x);
1581+
assert_eq!((-10..20).filter(p).try_fold(7, f), (0..10).try_fold(7, f));
1582+
assert_eq!((-10..20).filter(p).try_rfold(7, f), (0..10).try_rfold(7, f));
1583+
1584+
let mut iter = (0..40).filter(|&x| x % 2 == 1);
1585+
assert_eq!(iter.try_fold(0, i8::checked_add), None);
1586+
assert_eq!(iter.next(), Some(25));
1587+
assert_eq!(iter.try_rfold(0, i8::checked_add), None);
1588+
assert_eq!(iter.next_back(), Some(31));
1589+
}
1590+
1591+
#[test]
1592+
fn test_filter_map_try_folds() {
1593+
let mp = &|x| if 0 <= x && x < 10 { Some(x*2) } else { None };
1594+
let f = &|acc, x| i32::checked_add(2*acc, x);
1595+
assert_eq!((-9..20).filter_map(mp).try_fold(7, f), (0..10).map(|x| 2*x).try_fold(7, f));
1596+
assert_eq!((-9..20).filter_map(mp).try_rfold(7, f), (0..10).map(|x| 2*x).try_rfold(7, f));
1597+
1598+
let mut iter = (0..40).filter_map(|x| if x%2 == 1 { None } else { Some(x*2 + 10) });
1599+
assert_eq!(iter.try_fold(0, i8::checked_add), None);
1600+
assert_eq!(iter.next(), Some(38));
1601+
assert_eq!(iter.try_rfold(0, i8::checked_add), None);
1602+
assert_eq!(iter.next_back(), Some(78));
1603+
}
1604+
1605+
#[test]
1606+
fn test_enumerate_try_folds() {
1607+
let f = &|acc, (i, x)| usize::checked_add(2*acc, x/(i+1) + i);
1608+
assert_eq!((9..18).enumerate().try_fold(7, f), (0..9).map(|i| (i, i+9)).try_fold(7, f));
1609+
assert_eq!((9..18).enumerate().try_rfold(7, f), (0..9).map(|i| (i, i+9)).try_rfold(7, f));
1610+
1611+
let mut iter = (100..200).enumerate();
1612+
let f = &|acc, (i, x)| u8::checked_add(acc, u8::checked_div(x, i as u8 + 1)?);
1613+
assert_eq!(iter.try_fold(0, f), None);
1614+
assert_eq!(iter.next(), Some((7, 107)));
1615+
assert_eq!(iter.try_rfold(0, f), None);
1616+
assert_eq!(iter.next_back(), Some((11, 111)));
1617+
}
1618+
1619+
#[test]
1620+
fn test_peek_try_fold() {
1621+
let f = &|acc, x| i32::checked_add(2*acc, x);
1622+
assert_eq!((1..20).peekable().try_fold(7, f), (1..20).try_fold(7, f));
1623+
let mut iter = (1..20).peekable();
1624+
assert_eq!(iter.peek(), Some(&1));
1625+
assert_eq!(iter.try_fold(7, f), (1..20).try_fold(7, f));
1626+
1627+
let mut iter = [100, 20, 30, 40, 50, 60, 70].iter().cloned().peekable();
1628+
assert_eq!(iter.peek(), Some(&100));
1629+
assert_eq!(iter.try_fold(0, i8::checked_add), None);
1630+
assert_eq!(iter.peek(), Some(&40));
1631+
}
1632+
1633+
#[test]
1634+
fn test_skip_while_try_fold() {
1635+
let f = &|acc, x| i32::checked_add(2*acc, x);
1636+
fn p(&x: &i32) -> bool { (x % 10) <= 5 }
1637+
assert_eq!((1..20).skip_while(p).try_fold(7, f), (6..20).try_fold(7, f));
1638+
let mut iter = (1..20).skip_while(p);
1639+
assert_eq!(iter.nth(5), Some(11));
1640+
assert_eq!(iter.try_fold(7, f), (12..20).try_fold(7, f));
1641+
1642+
let mut iter = (0..50).skip_while(|&x| (x % 20) < 15);
1643+
assert_eq!(iter.try_fold(0, i8::checked_add), None);
1644+
assert_eq!(iter.next(), Some(23));
1645+
}
1646+
1647+
#[test]
1648+
fn test_take_while_folds() {
1649+
let f = &|acc, x| i32::checked_add(2*acc, x);
1650+
assert_eq!((1..20).take_while(|&x| x != 10).try_fold(7, f), (1..10).try_fold(7, f));
1651+
let mut iter = (1..20).take_while(|&x| x != 10);
1652+
assert_eq!(iter.try_fold(0, |x, y| Some(x+y)), Some((1..10).sum()));
1653+
assert_eq!(iter.next(), None, "flag should be set");
1654+
let iter = (1..20).take_while(|&x| x != 10);
1655+
assert_eq!(iter.fold(0, |x, y| x+y), (1..10).sum());
1656+
1657+
let mut iter = (10..50).take_while(|&x| x != 40);
1658+
assert_eq!(iter.try_fold(0, i8::checked_add), None);
1659+
assert_eq!(iter.next(), Some(20));
1660+
}
1661+
1662+
#[test]
1663+
fn test_skip_try_folds() {
1664+
let f = &|acc, x| i32::checked_add(2*acc, x);
1665+
assert_eq!((1..20).skip(9).try_fold(7, f), (10..20).try_fold(7, f));
1666+
assert_eq!((1..20).skip(9).try_rfold(7, f), (10..20).try_rfold(7, f));
1667+
1668+
let mut iter = (0..30).skip(10);
1669+
assert_eq!(iter.try_fold(0, i8::checked_add), None);
1670+
assert_eq!(iter.next(), Some(20));
1671+
assert_eq!(iter.try_rfold(0, i8::checked_add), None);
1672+
assert_eq!(iter.next_back(), Some(24));
1673+
}
1674+
1675+
#[test]
1676+
fn test_take_try_folds() {
1677+
let f = &|acc, x| i32::checked_add(2*acc, x);
1678+
assert_eq!((10..30).take(10).try_fold(7, f), (10..20).try_fold(7, f));
1679+
//assert_eq!((10..30).take(10).try_rfold(7, f), (10..20).try_rfold(7, f));
1680+
1681+
let mut iter = (10..30).take(20);
1682+
assert_eq!(iter.try_fold(0, i8::checked_add), None);
1683+
assert_eq!(iter.next(), Some(20));
1684+
//assert_eq!(iter.try_rfold(0, i8::checked_add), None);
1685+
//assert_eq!(iter.next_back(), Some(24));
1686+
}
1687+
1688+
#[test]
1689+
fn test_flat_map_try_folds() {
1690+
let f = &|acc, x| i32::checked_add(2*acc, x);
1691+
let mr = &|x| (5*x)..(5*x + 5);
1692+
assert_eq!((0..10).flat_map(mr).try_fold(7, f), (0..50).try_fold(7, f));
1693+
assert_eq!((0..10).flat_map(mr).try_rfold(7, f), (0..50).try_rfold(7, f));
1694+
let mut iter = (0..10).flat_map(mr);
1695+
iter.next(); iter.next_back(); // have front and back iters in progress
1696+
assert_eq!(iter.try_rfold(7, f), (1..49).try_rfold(7, f));
1697+
1698+
let mut iter = (0..10).flat_map(|x| (4*x)..(4*x + 4));
1699+
assert_eq!(iter.try_fold(0, i8::checked_add), None);
1700+
assert_eq!(iter.next(), Some(17));
1701+
assert_eq!(iter.try_rfold(0, i8::checked_add), None);
1702+
assert_eq!(iter.next_back(), Some(35));
1703+
}

src/libcore/tests/lib.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,7 @@
2424
#![feature(i128_type)]
2525
#![feature(inclusive_range)]
2626
#![feature(inclusive_range_syntax)]
27+
#![feature(iterator_try_fold)]
2728
#![feature(iter_rfind)]
2829
#![feature(iter_rfold)]
2930
#![feature(nonzero)]

src/libcore/tests/slice.rs

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -238,6 +238,23 @@ fn test_find_rfind() {
238238
assert_eq!(v.iter().rfind(|&&x| x <= 3), Some(&3));
239239
}
240240

241+
#[test]
242+
fn test_iter_folds() {
243+
let a = [1, 2, 3, 4, 5]; // len>4 so the unroll is used
244+
assert_eq!(a.iter().fold(0, |acc, &x| 2*acc + x), 57);
245+
assert_eq!(a.iter().rfold(0, |acc, &x| 2*acc + x), 129);
246+
let fold = |acc: i32, &x| acc.checked_mul(2)?.checked_add(x);
247+
assert_eq!(a.iter().try_fold(0, &fold), Some(57));
248+
assert_eq!(a.iter().try_rfold(0, &fold), Some(129));
249+
250+
// short-circuiting try_fold, through other methods
251+
let a = [0, 1, 2, 3, 5, 5, 5, 7, 8, 9];
252+
let mut iter = a.iter();
253+
assert_eq!(iter.position(|&x| x == 3), Some(3));
254+
assert_eq!(iter.rfind(|&&x| x == 5), Some(&5));
255+
assert_eq!(iter.len(), 2);
256+
}
257+
241258
#[test]
242259
fn test_rotate() {
243260
const N: usize = 600;

0 commit comments

Comments
 (0)