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