]> git.lizzy.rs Git - rust.git/blob - library/core/tests/array.rs
Rollup merge of #88523 - kpreid:category, r=yaahc
[rust.git] / library / core / tests / array.rs
1 use core::array;
2 use core::convert::TryFrom;
3
4 #[test]
5 fn array_from_ref() {
6     let value: String = "Hello World!".into();
7     let arr: &[String; 1] = array::from_ref(&value);
8     assert_eq!(&[value.clone()], arr);
9 }
10
11 #[test]
12 fn array_from_mut() {
13     let mut value: String = "Hello World".into();
14     let arr: &mut [String; 1] = array::from_mut(&mut value);
15     arr[0].push_str("!");
16     assert_eq!(&value, "Hello World!");
17 }
18
19 #[test]
20 fn array_try_from() {
21     macro_rules! test {
22         ($($N:expr)+) => {
23             $({
24                 type Array = [u8; $N];
25                 let array: Array = [0; $N];
26                 let slice: &[u8] = &array[..];
27
28                 let result = <&Array>::try_from(slice);
29                 assert_eq!(&array, result.unwrap());
30             })+
31         }
32     }
33     test! {
34          0  1  2  3  4  5  6  7  8  9
35         10 11 12 13 14 15 16 17 18 19
36         20 21 22 23 24 25 26 27 28 29
37         30 31 32
38     }
39 }
40
41 #[test]
42 fn iterator_collect() {
43     let arr = [0, 1, 2, 5, 9];
44     let v: Vec<_> = IntoIterator::into_iter(arr.clone()).collect();
45     assert_eq!(&arr[..], &v[..]);
46 }
47
48 #[test]
49 fn iterator_rev_collect() {
50     let arr = [0, 1, 2, 5, 9];
51     let v: Vec<_> = IntoIterator::into_iter(arr.clone()).rev().collect();
52     assert_eq!(&v[..], &[9, 5, 2, 1, 0]);
53 }
54
55 #[test]
56 fn iterator_nth() {
57     let v = [0, 1, 2, 3, 4];
58     for i in 0..v.len() {
59         assert_eq!(IntoIterator::into_iter(v.clone()).nth(i).unwrap(), v[i]);
60     }
61     assert_eq!(IntoIterator::into_iter(v.clone()).nth(v.len()), None);
62
63     let mut iter = IntoIterator::into_iter(v);
64     assert_eq!(iter.nth(2).unwrap(), v[2]);
65     assert_eq!(iter.nth(1).unwrap(), v[4]);
66 }
67
68 #[test]
69 fn iterator_last() {
70     let v = [0, 1, 2, 3, 4];
71     assert_eq!(IntoIterator::into_iter(v).last().unwrap(), 4);
72     assert_eq!(IntoIterator::into_iter([0]).last().unwrap(), 0);
73
74     let mut it = IntoIterator::into_iter([0, 9, 2, 4]);
75     assert_eq!(it.next_back(), Some(4));
76     assert_eq!(it.last(), Some(2));
77 }
78
79 #[test]
80 fn iterator_clone() {
81     let mut it = IntoIterator::into_iter([0, 2, 4, 6, 8]);
82     assert_eq!(it.next(), Some(0));
83     assert_eq!(it.next_back(), Some(8));
84     let mut clone = it.clone();
85     assert_eq!(it.next_back(), Some(6));
86     assert_eq!(clone.next_back(), Some(6));
87     assert_eq!(it.next_back(), Some(4));
88     assert_eq!(clone.next_back(), Some(4));
89     assert_eq!(it.next(), Some(2));
90     assert_eq!(clone.next(), Some(2));
91 }
92
93 #[test]
94 fn iterator_fused() {
95     let mut it = IntoIterator::into_iter([0, 9, 2]);
96     assert_eq!(it.next(), Some(0));
97     assert_eq!(it.next(), Some(9));
98     assert_eq!(it.next(), Some(2));
99     assert_eq!(it.next(), None);
100     assert_eq!(it.next(), None);
101     assert_eq!(it.next(), None);
102     assert_eq!(it.next(), None);
103     assert_eq!(it.next(), None);
104 }
105
106 #[test]
107 fn iterator_len() {
108     let mut it = IntoIterator::into_iter([0, 1, 2, 5, 9]);
109     assert_eq!(it.size_hint(), (5, Some(5)));
110     assert_eq!(it.len(), 5);
111     assert_eq!(it.is_empty(), false);
112
113     assert_eq!(it.next(), Some(0));
114     assert_eq!(it.size_hint(), (4, Some(4)));
115     assert_eq!(it.len(), 4);
116     assert_eq!(it.is_empty(), false);
117
118     assert_eq!(it.next_back(), Some(9));
119     assert_eq!(it.size_hint(), (3, Some(3)));
120     assert_eq!(it.len(), 3);
121     assert_eq!(it.is_empty(), false);
122
123     // Empty
124     let it = IntoIterator::into_iter([] as [String; 0]);
125     assert_eq!(it.size_hint(), (0, Some(0)));
126     assert_eq!(it.len(), 0);
127     assert_eq!(it.is_empty(), true);
128 }
129
130 #[test]
131 fn iterator_count() {
132     let v = [0, 1, 2, 3, 4];
133     assert_eq!(IntoIterator::into_iter(v.clone()).count(), 5);
134
135     let mut iter2 = IntoIterator::into_iter(v);
136     iter2.next();
137     iter2.next();
138     assert_eq!(iter2.count(), 3);
139 }
140
141 #[test]
142 fn iterator_flat_map() {
143     assert!((0..5).flat_map(|i| IntoIterator::into_iter([2 * i, 2 * i + 1])).eq(0..10));
144 }
145
146 #[test]
147 fn iterator_debug() {
148     let arr = [0, 1, 2, 5, 9];
149     assert_eq!(format!("{:?}", IntoIterator::into_iter(arr)), "IntoIter([0, 1, 2, 5, 9])",);
150 }
151
152 #[test]
153 fn iterator_drops() {
154     use core::cell::Cell;
155
156     // This test makes sure the correct number of elements are dropped. The `R`
157     // type is just a reference to a `Cell` that is incremented when an `R` is
158     // dropped.
159
160     #[derive(Clone)]
161     struct Foo<'a>(&'a Cell<usize>);
162
163     impl Drop for Foo<'_> {
164         fn drop(&mut self) {
165             self.0.set(self.0.get() + 1);
166         }
167     }
168
169     fn five(i: &Cell<usize>) -> [Foo<'_>; 5] {
170         // This is somewhat verbose because `Foo` does not implement `Copy`
171         // since it implements `Drop`. Consequently, we cannot write
172         // `[Foo(i); 5]`.
173         [Foo(i), Foo(i), Foo(i), Foo(i), Foo(i)]
174     }
175
176     // Simple: drop new iterator.
177     let i = Cell::new(0);
178     {
179         IntoIterator::into_iter(five(&i));
180     }
181     assert_eq!(i.get(), 5);
182
183     // Call `next()` once.
184     let i = Cell::new(0);
185     {
186         let mut iter = IntoIterator::into_iter(five(&i));
187         let _x = iter.next();
188         assert_eq!(i.get(), 0);
189         assert_eq!(iter.count(), 4);
190         assert_eq!(i.get(), 4);
191     }
192     assert_eq!(i.get(), 5);
193
194     // Check `clone` and calling `next`/`next_back`.
195     let i = Cell::new(0);
196     {
197         let mut iter = IntoIterator::into_iter(five(&i));
198         iter.next();
199         assert_eq!(i.get(), 1);
200         iter.next_back();
201         assert_eq!(i.get(), 2);
202
203         let mut clone = iter.clone();
204         assert_eq!(i.get(), 2);
205
206         iter.next();
207         assert_eq!(i.get(), 3);
208
209         clone.next();
210         assert_eq!(i.get(), 4);
211
212         assert_eq!(clone.count(), 2);
213         assert_eq!(i.get(), 6);
214     }
215     assert_eq!(i.get(), 8);
216
217     // Check via `nth`.
218     let i = Cell::new(0);
219     {
220         let mut iter = IntoIterator::into_iter(five(&i));
221         let _x = iter.nth(2);
222         assert_eq!(i.get(), 2);
223         let _y = iter.last();
224         assert_eq!(i.get(), 3);
225     }
226     assert_eq!(i.get(), 5);
227
228     // Check every element.
229     let i = Cell::new(0);
230     for (index, _x) in IntoIterator::into_iter(five(&i)).enumerate() {
231         assert_eq!(i.get(), index);
232     }
233     assert_eq!(i.get(), 5);
234
235     let i = Cell::new(0);
236     for (index, _x) in IntoIterator::into_iter(five(&i)).rev().enumerate() {
237         assert_eq!(i.get(), index);
238     }
239     assert_eq!(i.get(), 5);
240 }
241
242 // This test does not work on targets without panic=unwind support.
243 // To work around this problem, test is marked is should_panic, so it will
244 // be automagically skipped on unsuitable targets, such as
245 // wasm32-unknown-unkown.
246 //
247 // It means that we use panic for indicating success.
248 #[test]
249 #[should_panic(expected = "test succeeded")]
250 fn array_default_impl_avoids_leaks_on_panic() {
251     use core::sync::atomic::{AtomicUsize, Ordering::Relaxed};
252     static COUNTER: AtomicUsize = AtomicUsize::new(0);
253     #[derive(Debug)]
254     struct Bomb(usize);
255
256     impl Default for Bomb {
257         fn default() -> Bomb {
258             if COUNTER.load(Relaxed) == 3 {
259                 panic!("bomb limit exceeded");
260             }
261
262             COUNTER.fetch_add(1, Relaxed);
263             Bomb(COUNTER.load(Relaxed))
264         }
265     }
266
267     impl Drop for Bomb {
268         fn drop(&mut self) {
269             COUNTER.fetch_sub(1, Relaxed);
270         }
271     }
272
273     let res = std::panic::catch_unwind(|| <[Bomb; 5]>::default());
274     let panic_msg = match res {
275         Ok(_) => unreachable!(),
276         Err(p) => p.downcast::<&'static str>().unwrap(),
277     };
278     assert_eq!(*panic_msg, "bomb limit exceeded");
279     // check that all bombs are successfully dropped
280     assert_eq!(COUNTER.load(Relaxed), 0);
281     panic!("test succeeded")
282 }
283
284 #[test]
285 fn empty_array_is_always_default() {
286     struct DoesNotImplDefault;
287
288     let _arr = <[DoesNotImplDefault; 0]>::default();
289 }
290
291 #[test]
292 fn array_map() {
293     let a = [1, 2, 3];
294     let b = a.map(|v| v + 1);
295     assert_eq!(b, [2, 3, 4]);
296
297     let a = [1u8, 2, 3];
298     let b = a.map(|v| v as u64);
299     assert_eq!(b, [1, 2, 3]);
300 }
301
302 // See note on above test for why `should_panic` is used.
303 #[test]
304 #[should_panic(expected = "test succeeded")]
305 fn array_map_drop_safety() {
306     use core::sync::atomic::AtomicUsize;
307     use core::sync::atomic::Ordering;
308     static DROPPED: AtomicUsize = AtomicUsize::new(0);
309     struct DropCounter;
310     impl Drop for DropCounter {
311         fn drop(&mut self) {
312             DROPPED.fetch_add(1, Ordering::SeqCst);
313         }
314     }
315
316     let num_to_create = 5;
317     let success = std::panic::catch_unwind(|| {
318         let items = [0; 10];
319         let mut nth = 0;
320         items.map(|_| {
321             assert!(nth < num_to_create);
322             nth += 1;
323             DropCounter
324         });
325     });
326     assert!(success.is_err());
327     assert_eq!(DROPPED.load(Ordering::SeqCst), num_to_create);
328     panic!("test succeeded")
329 }
330
331 #[test]
332 fn cell_allows_array_cycle() {
333     use core::cell::Cell;
334
335     #[derive(Debug)]
336     struct B<'a> {
337         a: [Cell<Option<&'a B<'a>>>; 2],
338     }
339
340     impl<'a> B<'a> {
341         fn new() -> B<'a> {
342             B { a: [Cell::new(None), Cell::new(None)] }
343         }
344     }
345
346     let b1 = B::new();
347     let b2 = B::new();
348     let b3 = B::new();
349
350     b1.a[0].set(Some(&b2));
351     b1.a[1].set(Some(&b3));
352
353     b2.a[0].set(Some(&b2));
354     b2.a[1].set(Some(&b3));
355
356     b3.a[0].set(Some(&b1));
357     b3.a[1].set(Some(&b2));
358 }