]> git.lizzy.rs Git - rust.git/blob - library/core/tests/iter/adapters/chain.rs
Fix Iterator::advance_by contract inconsistency
[rust.git] / library / core / tests / iter / adapters / chain.rs
1 use super::*;
2 use core::iter::*;
3
4 #[test]
5 fn test_iterator_chain() {
6     let xs = [0, 1, 2, 3, 4, 5];
7     let ys = [30, 40, 50, 60];
8     let expected = [0, 1, 2, 3, 4, 5, 30, 40, 50, 60];
9     let it = xs.iter().chain(&ys);
10     let mut i = 0;
11     for &x in it {
12         assert_eq!(x, expected[i]);
13         i += 1;
14     }
15     assert_eq!(i, expected.len());
16
17     let ys = (30..).step_by(10).take(4);
18     let it = xs.iter().cloned().chain(ys);
19     let mut i = 0;
20     for x in it {
21         assert_eq!(x, expected[i]);
22         i += 1;
23     }
24     assert_eq!(i, expected.len());
25 }
26
27 #[test]
28 fn test_iterator_chain_advance_by() {
29     fn test_chain(xs: &[i32], ys: &[i32]) {
30         let len = xs.len() + ys.len();
31
32         for i in 0..xs.len() {
33             let mut iter = Unfuse::new(xs).chain(Unfuse::new(ys));
34             iter.advance_by(i).unwrap();
35             assert_eq!(iter.next(), Some(&xs[i]));
36             assert_eq!(iter.advance_by(100), Err(len - i - 1));
37             iter.advance_by(0).unwrap();
38         }
39
40         for i in 0..ys.len() {
41             let mut iter = Unfuse::new(xs).chain(Unfuse::new(ys));
42             iter.advance_by(xs.len() + i).unwrap();
43             assert_eq!(iter.next(), Some(&ys[i]));
44             assert_eq!(iter.advance_by(100), Err(ys.len() - i - 1));
45             iter.advance_by(0).unwrap();
46         }
47
48         let mut iter = xs.iter().chain(ys);
49         iter.advance_by(len).unwrap();
50         assert_eq!(iter.next(), None);
51         iter.advance_by(0).unwrap();
52
53         let mut iter = xs.iter().chain(ys);
54         assert_eq!(iter.advance_by(len + 1), Err(len));
55         iter.advance_by(0).unwrap();
56     }
57
58     test_chain(&[], &[]);
59     test_chain(&[], &[0, 1, 2, 3, 4, 5]);
60     test_chain(&[0, 1, 2, 3, 4, 5], &[]);
61     test_chain(&[0, 1, 2, 3, 4, 5], &[30, 40, 50, 60]);
62 }
63
64 #[test]
65 fn test_iterator_chain_advance_back_by() {
66     fn test_chain(xs: &[i32], ys: &[i32]) {
67         let len = xs.len() + ys.len();
68
69         for i in 0..ys.len() {
70             let mut iter = Unfuse::new(xs).chain(Unfuse::new(ys));
71             iter.advance_back_by(i).unwrap();
72             assert_eq!(iter.next_back(), Some(&ys[ys.len() - i - 1]));
73             assert_eq!(iter.advance_back_by(100), Err(len - i - 1));
74             iter.advance_back_by(0).unwrap();
75         }
76
77         for i in 0..xs.len() {
78             let mut iter = Unfuse::new(xs).chain(Unfuse::new(ys));
79             iter.advance_back_by(ys.len() + i).unwrap();
80             assert_eq!(iter.next_back(), Some(&xs[xs.len() - i - 1]));
81             assert_eq!(iter.advance_back_by(100), Err(xs.len() - i - 1));
82             iter.advance_back_by(0).unwrap();
83         }
84
85         let mut iter = xs.iter().chain(ys);
86         iter.advance_back_by(len).unwrap();
87         assert_eq!(iter.next_back(), None);
88         iter.advance_back_by(0).unwrap();
89
90         let mut iter = xs.iter().chain(ys);
91         assert_eq!(iter.advance_back_by(len + 1), Err(len));
92         iter.advance_back_by(0).unwrap();
93     }
94
95     test_chain(&[], &[]);
96     test_chain(&[], &[0, 1, 2, 3, 4, 5]);
97     test_chain(&[0, 1, 2, 3, 4, 5], &[]);
98     test_chain(&[0, 1, 2, 3, 4, 5], &[30, 40, 50, 60]);
99 }
100
101 #[test]
102 fn test_iterator_chain_nth() {
103     let xs = [0, 1, 2, 3, 4, 5];
104     let ys = [30, 40, 50, 60];
105     let zs = [];
106     let expected = [0, 1, 2, 3, 4, 5, 30, 40, 50, 60];
107     for (i, x) in expected.iter().enumerate() {
108         assert_eq!(Some(x), xs.iter().chain(&ys).nth(i));
109     }
110     assert_eq!(zs.iter().chain(&xs).nth(0), Some(&0));
111
112     let mut it = xs.iter().chain(&zs);
113     assert_eq!(it.nth(5), Some(&5));
114     assert_eq!(it.next(), None);
115 }
116
117 #[test]
118 fn test_iterator_chain_nth_back() {
119     let xs = [0, 1, 2, 3, 4, 5];
120     let ys = [30, 40, 50, 60];
121     let zs = [];
122     let expected = [0, 1, 2, 3, 4, 5, 30, 40, 50, 60];
123     for (i, x) in expected.iter().rev().enumerate() {
124         assert_eq!(Some(x), xs.iter().chain(&ys).nth_back(i));
125     }
126     assert_eq!(zs.iter().chain(&xs).nth_back(0), Some(&5));
127
128     let mut it = xs.iter().chain(&zs);
129     assert_eq!(it.nth_back(5), Some(&0));
130     assert_eq!(it.next(), None);
131 }
132
133 #[test]
134 fn test_iterator_chain_last() {
135     let xs = [0, 1, 2, 3, 4, 5];
136     let ys = [30, 40, 50, 60];
137     let zs = [];
138     assert_eq!(xs.iter().chain(&ys).last(), Some(&60));
139     assert_eq!(zs.iter().chain(&ys).last(), Some(&60));
140     assert_eq!(ys.iter().chain(&zs).last(), Some(&60));
141     assert_eq!(zs.iter().chain(&zs).last(), None);
142 }
143
144 #[test]
145 fn test_iterator_chain_count() {
146     let xs = [0, 1, 2, 3, 4, 5];
147     let ys = [30, 40, 50, 60];
148     let zs = [];
149     assert_eq!(xs.iter().chain(&ys).count(), 10);
150     assert_eq!(zs.iter().chain(&ys).count(), 4);
151 }
152
153 #[test]
154 fn test_iterator_chain_find() {
155     let xs = [0, 1, 2, 3, 4, 5];
156     let ys = [30, 40, 50, 60];
157     let mut iter = xs.iter().chain(&ys);
158     assert_eq!(iter.find(|&&i| i == 4), Some(&4));
159     assert_eq!(iter.next(), Some(&5));
160     assert_eq!(iter.find(|&&i| i == 40), Some(&40));
161     assert_eq!(iter.next(), Some(&50));
162     assert_eq!(iter.find(|&&i| i == 100), None);
163     assert_eq!(iter.next(), None);
164 }
165
166 #[test]
167 fn test_iterator_chain_size_hint() {
168     // this chains an iterator of length 0 with an iterator of length 1,
169     // so after calling `.next()` once, the iterator is empty and the
170     // state is `ChainState::Back`. `.size_hint()` should now disregard
171     // the size hint of the left iterator
172     let mut iter = Toggle { is_empty: true }.chain(once(()));
173     assert_eq!(iter.next(), Some(()));
174     assert_eq!(iter.size_hint(), (0, Some(0)));
175
176     let mut iter = once(()).chain(Toggle { is_empty: true });
177     assert_eq!(iter.next_back(), Some(()));
178     assert_eq!(iter.size_hint(), (0, Some(0)));
179 }
180
181 #[test]
182 fn test_iterator_chain_unfused() {
183     // Chain shouldn't be fused in its second iterator, depending on direction
184     let mut iter = NonFused::new(empty()).chain(Toggle { is_empty: true });
185     assert!(iter.next().is_none());
186     assert!(iter.next().is_some());
187     assert!(iter.next().is_none());
188
189     let mut iter = Toggle { is_empty: true }.chain(NonFused::new(empty()));
190     assert!(iter.next_back().is_none());
191     assert!(iter.next_back().is_some());
192     assert!(iter.next_back().is_none());
193 }
194
195 #[test]
196 fn test_chain_fold() {
197     let xs = [1, 2, 3];
198     let ys = [1, 2, 0];
199
200     let mut iter = xs.iter().chain(&ys);
201     iter.next();
202     let mut result = Vec::new();
203     iter.fold((), |(), &elt| result.push(elt));
204     assert_eq!(&[2, 3, 1, 2, 0], &result[..]);
205 }
206
207 #[test]
208 fn test_chain_try_folds() {
209     let c = || (0..10).chain(10..20);
210
211     let f = &|acc, x| i32::checked_add(2 * acc, x);
212     assert_eq!(c().try_fold(7, f), (0..20).try_fold(7, f));
213     assert_eq!(c().try_rfold(7, f), (0..20).rev().try_fold(7, f));
214
215     let mut iter = c();
216     assert_eq!(iter.position(|x| x == 5), Some(5));
217     assert_eq!(iter.next(), Some(6), "stopped in front, state Both");
218     assert_eq!(iter.position(|x| x == 13), Some(6));
219     assert_eq!(iter.next(), Some(14), "stopped in back, state Back");
220     assert_eq!(iter.try_fold(0, |acc, x| Some(acc + x)), Some((15..20).sum()));
221
222     let mut iter = c().rev(); // use rev to access try_rfold
223     assert_eq!(iter.position(|x| x == 15), Some(4));
224     assert_eq!(iter.next(), Some(14), "stopped in back, state Both");
225     assert_eq!(iter.position(|x| x == 5), Some(8));
226     assert_eq!(iter.next(), Some(4), "stopped in front, state Front");
227     assert_eq!(iter.try_fold(0, |acc, x| Some(acc + x)), Some((0..4).sum()));
228
229     let mut iter = c();
230     iter.by_ref().rev().nth(14); // skip the last 15, ending in state Front
231     assert_eq!(iter.try_fold(7, f), (0..5).try_fold(7, f));
232
233     let mut iter = c();
234     iter.nth(14); // skip the first 15, ending in state Back
235     assert_eq!(iter.try_rfold(7, f), (15..20).try_rfold(7, f));
236 }
237
238 #[test]
239 fn test_double_ended_chain() {
240     let xs = [1, 2, 3, 4, 5];
241     let ys = [7, 9, 11];
242     let mut it = xs.iter().chain(&ys).rev();
243     assert_eq!(it.next().unwrap(), &11);
244     assert_eq!(it.next().unwrap(), &9);
245     assert_eq!(it.next_back().unwrap(), &1);
246     assert_eq!(it.next_back().unwrap(), &2);
247     assert_eq!(it.next_back().unwrap(), &3);
248     assert_eq!(it.next_back().unwrap(), &4);
249     assert_eq!(it.next_back().unwrap(), &5);
250     assert_eq!(it.next_back().unwrap(), &7);
251     assert_eq!(it.next_back(), None);
252
253     // test that .chain() is well behaved with an unfused iterator
254     struct CrazyIterator(bool);
255     impl CrazyIterator {
256         fn new() -> CrazyIterator {
257             CrazyIterator(false)
258         }
259     }
260     impl Iterator for CrazyIterator {
261         type Item = i32;
262         fn next(&mut self) -> Option<i32> {
263             if self.0 {
264                 Some(99)
265             } else {
266                 self.0 = true;
267                 None
268             }
269         }
270     }
271
272     impl DoubleEndedIterator for CrazyIterator {
273         fn next_back(&mut self) -> Option<i32> {
274             self.next()
275         }
276     }
277
278     assert_eq!(CrazyIterator::new().chain(0..10).rev().last(), Some(0));
279     assert!((0..10).chain(CrazyIterator::new()).rev().any(|i| i == 0));
280 }