]> git.proxmox.com Git - rustc.git/blob - library/core/tests/iter/adapters/map_windows.rs
New upstream version 1.73.0+dfsg1
[rustc.git] / library / core / tests / iter / adapters / map_windows.rs
1 use std::sync::atomic::{AtomicUsize, Ordering::SeqCst};
2
3 #[cfg(not(panic = "abort"))]
4 mod drop_checks {
5 //! These tests mainly make sure the elements are correctly dropped.
6 use std::sync::atomic::{AtomicBool, AtomicUsize, Ordering::SeqCst};
7
8 #[derive(Debug)]
9 struct DropInfo {
10 dropped_twice: AtomicBool,
11 alive_count: AtomicUsize,
12 }
13
14 impl DropInfo {
15 const fn new() -> Self {
16 Self { dropped_twice: AtomicBool::new(false), alive_count: AtomicUsize::new(0) }
17 }
18
19 #[track_caller]
20 fn check(&self) {
21 assert!(!self.dropped_twice.load(SeqCst), "a value was dropped twice");
22 assert_eq!(self.alive_count.load(SeqCst), 0);
23 }
24 }
25
26 #[derive(Debug)]
27 struct DropCheck<'a> {
28 info: &'a DropInfo,
29 was_dropped: bool,
30 }
31
32 impl<'a> DropCheck<'a> {
33 fn new(info: &'a DropInfo) -> Self {
34 info.alive_count.fetch_add(1, SeqCst);
35
36 Self { info, was_dropped: false }
37 }
38 }
39
40 impl Drop for DropCheck<'_> {
41 fn drop(&mut self) {
42 if self.was_dropped {
43 self.info.dropped_twice.store(true, SeqCst);
44 }
45 self.was_dropped = true;
46
47 self.info.alive_count.fetch_sub(1, SeqCst);
48 }
49 }
50
51 fn iter(info: &DropInfo, len: usize, panic_at: usize) -> impl Iterator<Item = DropCheck<'_>> {
52 (0..len).map(move |i| {
53 if i == panic_at {
54 panic!("intended panic");
55 }
56 DropCheck::new(info)
57 })
58 }
59
60 #[track_caller]
61 fn check<const N: usize>(len: usize, panic_at: usize) {
62 check_drops(|info| {
63 iter(info, len, panic_at).map_windows(|_: &[_; N]| {}).last();
64 });
65 }
66
67 #[track_caller]
68 fn check_drops(f: impl FnOnce(&DropInfo)) {
69 let info = DropInfo::new();
70 let _ = std::panic::catch_unwind(std::panic::AssertUnwindSafe(|| {
71 f(&info);
72 }));
73 info.check();
74 }
75
76 #[test]
77 fn no_iter_panic_n1() {
78 check::<1>(0, 100);
79 check::<1>(1, 100);
80 check::<1>(2, 100);
81 check::<1>(13, 100);
82 }
83
84 #[test]
85 fn no_iter_panic_n2() {
86 check::<2>(0, 100);
87 check::<2>(1, 100);
88 check::<2>(2, 100);
89 check::<2>(3, 100);
90 check::<2>(13, 100);
91 }
92
93 #[test]
94 fn no_iter_panic_n5() {
95 check::<5>(0, 100);
96 check::<5>(1, 100);
97 check::<5>(2, 100);
98 check::<5>(13, 100);
99 check::<5>(30, 100);
100 }
101
102 #[test]
103 fn panic_in_first_batch() {
104 check::<1>(7, 0);
105
106 check::<2>(7, 0);
107 check::<2>(7, 1);
108
109 check::<3>(7, 0);
110 check::<3>(7, 1);
111 check::<3>(7, 2);
112 }
113
114 #[test]
115 fn panic_in_middle() {
116 check::<1>(7, 1);
117 check::<1>(7, 5);
118 check::<1>(7, 6);
119
120 check::<2>(7, 2);
121 check::<2>(7, 5);
122 check::<2>(7, 6);
123
124 check::<5>(13, 5);
125 check::<5>(13, 8);
126 check::<5>(13, 12);
127 }
128
129 #[test]
130 fn len_equals_n() {
131 check::<1>(1, 100);
132 check::<1>(1, 0);
133
134 check::<2>(2, 100);
135 check::<2>(2, 0);
136 check::<2>(2, 1);
137
138 check::<5>(5, 100);
139 check::<5>(5, 0);
140 check::<5>(5, 1);
141 check::<5>(5, 4);
142 }
143 }
144
145 #[test]
146 fn output_n1() {
147 assert_eq!("".chars().map_windows(|[c]| *c).collect::<Vec<_>>(), vec![]);
148 assert_eq!("x".chars().map_windows(|[c]| *c).collect::<Vec<_>>(), vec!['x']);
149 assert_eq!("abcd".chars().map_windows(|[c]| *c).collect::<Vec<_>>(), vec!['a', 'b', 'c', 'd']);
150 }
151
152 #[test]
153 fn output_n2() {
154 assert_eq!(
155 "".chars().map_windows(|a: &[_; 2]| *a).collect::<Vec<_>>(),
156 <Vec<[char; 2]>>::new(),
157 );
158 assert_eq!("ab".chars().map_windows(|a: &[_; 2]| *a).collect::<Vec<_>>(), vec![['a', 'b']]);
159 assert_eq!(
160 "abcd".chars().map_windows(|a: &[_; 2]| *a).collect::<Vec<_>>(),
161 vec![['a', 'b'], ['b', 'c'], ['c', 'd']],
162 );
163 }
164
165 #[test]
166 fn test_case_from_pr_82413_comment() {
167 for () in std::iter::repeat("0".to_owned()).map_windows(|_: &[_; 3]| {}).take(4) {}
168 }
169
170 #[test]
171 #[should_panic = "array in `Iterator::map_windows` must contain more than 0 elements"]
172 fn check_zero_window() {
173 let _ = std::iter::repeat(0).map_windows(|_: &[_; 0]| ());
174 }
175
176 #[test]
177 fn test_zero_sized_type() {
178 #[derive(Copy, Clone, Debug, Eq, PartialEq)]
179 struct Data;
180 let data: Vec<_> =
181 std::iter::repeat(Data).take(10).map_windows(|arr: &[Data; 5]| *arr).collect();
182 assert_eq!(data, [[Data; 5]; 6]);
183 }
184
185 #[test]
186 #[should_panic = "array size of `Iterator::map_windows` is too large"]
187 fn test_too_large_array_size() {
188 let _ = std::iter::repeat(()).map_windows(|arr: &[(); usize::MAX]| *arr);
189 }
190
191 #[test]
192 fn test_laziness() {
193 let counter = AtomicUsize::new(0);
194 let mut iter = (0..5)
195 .inspect(|_| {
196 counter.fetch_add(1, SeqCst);
197 })
198 .map_windows(|arr: &[i32; 2]| *arr);
199 assert_eq!(counter.load(SeqCst), 0);
200
201 assert_eq!(iter.next(), Some([0, 1]));
202 // The first iteration consumes N items (N = 2).
203 assert_eq!(counter.load(SeqCst), 2);
204
205 assert_eq!(iter.next(), Some([1, 2]));
206 assert_eq!(counter.load(SeqCst), 3);
207
208 assert_eq!(iter.next(), Some([2, 3]));
209 assert_eq!(counter.load(SeqCst), 4);
210
211 assert_eq!(iter.next(), Some([3, 4]));
212 assert_eq!(counter.load(SeqCst), 5);
213
214 assert_eq!(iter.next(), None);
215 assert_eq!(counter.load(SeqCst), 5);
216 }
217
218 #[test]
219 fn test_size_hint() {
220 struct SizeHintCheckHelper((usize, Option<usize>));
221
222 impl Iterator for SizeHintCheckHelper {
223 type Item = i32;
224
225 fn next(&mut self) -> Option<i32> {
226 let (ref mut lo, ref mut hi) = self.0;
227 let next = (*hi != Some(0)).then_some(0);
228 *lo = lo.saturating_sub(1);
229 if let Some(hi) = hi {
230 *hi = hi.saturating_sub(1);
231 }
232 next
233 }
234
235 fn size_hint(&self) -> (usize, Option<usize>) {
236 self.0
237 }
238 }
239
240 fn check_size_hint<const N: usize>(
241 size_hint: (usize, Option<usize>),
242 mut mapped_size_hint: (usize, Option<usize>),
243 ) {
244 let mut iter = SizeHintCheckHelper(size_hint);
245 let mut mapped_iter = iter.by_ref().map_windows(|_: &[_; N]| ());
246 while mapped_iter.size_hint().0 > 0 {
247 assert_eq!(mapped_iter.size_hint(), mapped_size_hint);
248 assert!(mapped_iter.next().is_some());
249 mapped_size_hint.0 -= 1;
250 mapped_size_hint.1 = mapped_size_hint.1.map(|hi| hi.saturating_sub(1));
251 }
252 }
253
254 check_size_hint::<1>((0, None), (0, None));
255 check_size_hint::<1>((0, Some(0)), (0, Some(0)));
256 check_size_hint::<1>((0, Some(2)), (0, Some(2)));
257 check_size_hint::<1>((1, None), (1, None));
258 check_size_hint::<1>((1, Some(1)), (1, Some(1)));
259 check_size_hint::<1>((1, Some(4)), (1, Some(4)));
260 check_size_hint::<1>((5, None), (5, None));
261 check_size_hint::<1>((5, Some(5)), (5, Some(5)));
262 check_size_hint::<1>((5, Some(10)), (5, Some(10)));
263
264 check_size_hint::<2>((0, None), (0, None));
265 check_size_hint::<2>((0, Some(0)), (0, Some(0)));
266 check_size_hint::<2>((0, Some(2)), (0, Some(1)));
267 check_size_hint::<2>((1, None), (0, None));
268 check_size_hint::<2>((1, Some(1)), (0, Some(0)));
269 check_size_hint::<2>((1, Some(4)), (0, Some(3)));
270 check_size_hint::<2>((5, None), (4, None));
271 check_size_hint::<2>((5, Some(5)), (4, Some(4)));
272 check_size_hint::<2>((5, Some(10)), (4, Some(9)));
273
274 check_size_hint::<5>((0, None), (0, None));
275 check_size_hint::<5>((0, Some(0)), (0, Some(0)));
276 check_size_hint::<5>((0, Some(2)), (0, Some(0)));
277 check_size_hint::<5>((1, None), (0, None));
278 check_size_hint::<5>((1, Some(1)), (0, Some(0)));
279 check_size_hint::<5>((1, Some(4)), (0, Some(0)));
280 check_size_hint::<5>((5, None), (1, None));
281 check_size_hint::<5>((5, Some(5)), (1, Some(1)));
282 check_size_hint::<5>((5, Some(10)), (1, Some(6)));
283 }