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