1 use core::array;
2 use core::convert::TryFrom;
3 use core::sync::atomic::{AtomicUsize, Ordering};
4 
5 #[test]
array_from_ref()6 fn array_from_ref() {
7     let value: String = "Hello World!".into();
8     let arr: &[String; 1] = array::from_ref(&value);
9     assert_eq!(&[value.clone()], arr);
10 
11     const VALUE: &&str = &"Hello World!";
12     const ARR: &[&str; 1] = array::from_ref(VALUE);
13     assert_eq!(&[*VALUE], ARR);
14     assert!(core::ptr::eq(VALUE, &ARR[0]));
15 }
16 
17 #[test]
array_from_mut()18 fn array_from_mut() {
19     let mut value: String = "Hello World".into();
20     let arr: &mut [String; 1] = array::from_mut(&mut value);
21     arr[0].push_str("!");
22     assert_eq!(&value, "Hello World!");
23 }
24 
25 #[test]
array_try_from()26 fn array_try_from() {
27     macro_rules! test {
28         ($($N:expr)+) => {
29             $({
30                 type Array = [u8; $N];
31                 let array: Array = [0; $N];
32                 let slice: &[u8] = &array[..];
33 
34                 let result = <&Array>::try_from(slice);
35                 assert_eq!(&array, result.unwrap());
36             })+
37         }
38     }
39     test! {
40          0  1  2  3  4  5  6  7  8  9
41         10 11 12 13 14 15 16 17 18 19
42         20 21 22 23 24 25 26 27 28 29
43         30 31 32
44     }
45 }
46 
47 #[test]
iterator_collect()48 fn iterator_collect() {
49     let arr = [0, 1, 2, 5, 9];
50     let v: Vec<_> = IntoIterator::into_iter(arr.clone()).collect();
51     assert_eq!(&arr[..], &v[..]);
52 }
53 
54 #[test]
iterator_rev_collect()55 fn iterator_rev_collect() {
56     let arr = [0, 1, 2, 5, 9];
57     let v: Vec<_> = IntoIterator::into_iter(arr.clone()).rev().collect();
58     assert_eq!(&v[..], &[9, 5, 2, 1, 0]);
59 }
60 
61 #[test]
iterator_nth()62 fn iterator_nth() {
63     let v = [0, 1, 2, 3, 4];
64     for i in 0..v.len() {
65         assert_eq!(IntoIterator::into_iter(v.clone()).nth(i).unwrap(), v[i]);
66     }
67     assert_eq!(IntoIterator::into_iter(v.clone()).nth(v.len()), None);
68 
69     let mut iter = IntoIterator::into_iter(v);
70     assert_eq!(iter.nth(2).unwrap(), v[2]);
71     assert_eq!(iter.nth(1).unwrap(), v[4]);
72 }
73 
74 #[test]
iterator_last()75 fn iterator_last() {
76     let v = [0, 1, 2, 3, 4];
77     assert_eq!(IntoIterator::into_iter(v).last().unwrap(), 4);
78     assert_eq!(IntoIterator::into_iter([0]).last().unwrap(), 0);
79 
80     let mut it = IntoIterator::into_iter([0, 9, 2, 4]);
81     assert_eq!(it.next_back(), Some(4));
82     assert_eq!(it.last(), Some(2));
83 }
84 
85 #[test]
iterator_clone()86 fn iterator_clone() {
87     let mut it = IntoIterator::into_iter([0, 2, 4, 6, 8]);
88     assert_eq!(it.next(), Some(0));
89     assert_eq!(it.next_back(), Some(8));
90     let mut clone = it.clone();
91     assert_eq!(it.next_back(), Some(6));
92     assert_eq!(clone.next_back(), Some(6));
93     assert_eq!(it.next_back(), Some(4));
94     assert_eq!(clone.next_back(), Some(4));
95     assert_eq!(it.next(), Some(2));
96     assert_eq!(clone.next(), Some(2));
97 }
98 
99 #[test]
iterator_fused()100 fn iterator_fused() {
101     let mut it = IntoIterator::into_iter([0, 9, 2]);
102     assert_eq!(it.next(), Some(0));
103     assert_eq!(it.next(), Some(9));
104     assert_eq!(it.next(), Some(2));
105     assert_eq!(it.next(), None);
106     assert_eq!(it.next(), None);
107     assert_eq!(it.next(), None);
108     assert_eq!(it.next(), None);
109     assert_eq!(it.next(), None);
110 }
111 
112 #[test]
iterator_len()113 fn iterator_len() {
114     let mut it = IntoIterator::into_iter([0, 1, 2, 5, 9]);
115     assert_eq!(it.size_hint(), (5, Some(5)));
116     assert_eq!(it.len(), 5);
117     assert_eq!(it.is_empty(), false);
118 
119     assert_eq!(it.next(), Some(0));
120     assert_eq!(it.size_hint(), (4, Some(4)));
121     assert_eq!(it.len(), 4);
122     assert_eq!(it.is_empty(), false);
123 
124     assert_eq!(it.next_back(), Some(9));
125     assert_eq!(it.size_hint(), (3, Some(3)));
126     assert_eq!(it.len(), 3);
127     assert_eq!(it.is_empty(), false);
128 
129     // Empty
130     let it = IntoIterator::into_iter([] as [String; 0]);
131     assert_eq!(it.size_hint(), (0, Some(0)));
132     assert_eq!(it.len(), 0);
133     assert_eq!(it.is_empty(), true);
134 }
135 
136 #[test]
iterator_count()137 fn iterator_count() {
138     let v = [0, 1, 2, 3, 4];
139     assert_eq!(IntoIterator::into_iter(v.clone()).count(), 5);
140 
141     let mut iter2 = IntoIterator::into_iter(v);
142     iter2.next();
143     iter2.next();
144     assert_eq!(iter2.count(), 3);
145 }
146 
147 #[test]
iterator_flat_map()148 fn iterator_flat_map() {
149     assert!((0..5).flat_map(|i| IntoIterator::into_iter([2 * i, 2 * i + 1])).eq(0..10));
150 }
151 
152 #[test]
iterator_debug()153 fn iterator_debug() {
154     let arr = [0, 1, 2, 5, 9];
155     assert_eq!(format!("{:?}", IntoIterator::into_iter(arr)), "IntoIter([0, 1, 2, 5, 9])",);
156 }
157 
158 #[test]
iterator_drops()159 fn iterator_drops() {
160     use core::cell::Cell;
161 
162     // This test makes sure the correct number of elements are dropped. The `R`
163     // type is just a reference to a `Cell` that is incremented when an `R` is
164     // dropped.
165 
166     #[derive(Clone)]
167     struct Foo<'a>(&'a Cell<usize>);
168 
169     impl Drop for Foo<'_> {
170         fn drop(&mut self) {
171             self.0.set(self.0.get() + 1);
172         }
173     }
174 
175     fn five(i: &Cell<usize>) -> [Foo<'_>; 5] {
176         // This is somewhat verbose because `Foo` does not implement `Copy`
177         // since it implements `Drop`. Consequently, we cannot write
178         // `[Foo(i); 5]`.
179         [Foo(i), Foo(i), Foo(i), Foo(i), Foo(i)]
180     }
181 
182     // Simple: drop new iterator.
183     let i = Cell::new(0);
184     {
185         IntoIterator::into_iter(five(&i));
186     }
187     assert_eq!(i.get(), 5);
188 
189     // Call `next()` once.
190     let i = Cell::new(0);
191     {
192         let mut iter = IntoIterator::into_iter(five(&i));
193         let _x = iter.next();
194         assert_eq!(i.get(), 0);
195         assert_eq!(iter.count(), 4);
196         assert_eq!(i.get(), 4);
197     }
198     assert_eq!(i.get(), 5);
199 
200     // Check `clone` and calling `next`/`next_back`.
201     let i = Cell::new(0);
202     {
203         let mut iter = IntoIterator::into_iter(five(&i));
204         iter.next();
205         assert_eq!(i.get(), 1);
206         iter.next_back();
207         assert_eq!(i.get(), 2);
208 
209         let mut clone = iter.clone();
210         assert_eq!(i.get(), 2);
211 
212         iter.next();
213         assert_eq!(i.get(), 3);
214 
215         clone.next();
216         assert_eq!(i.get(), 4);
217 
218         assert_eq!(clone.count(), 2);
219         assert_eq!(i.get(), 6);
220     }
221     assert_eq!(i.get(), 8);
222 
223     // Check via `nth`.
224     let i = Cell::new(0);
225     {
226         let mut iter = IntoIterator::into_iter(five(&i));
227         let _x = iter.nth(2);
228         assert_eq!(i.get(), 2);
229         let _y = iter.last();
230         assert_eq!(i.get(), 3);
231     }
232     assert_eq!(i.get(), 5);
233 
234     // Check every element.
235     let i = Cell::new(0);
236     for (index, _x) in IntoIterator::into_iter(five(&i)).enumerate() {
237         assert_eq!(i.get(), index);
238     }
239     assert_eq!(i.get(), 5);
240 
241     let i = Cell::new(0);
242     for (index, _x) in IntoIterator::into_iter(five(&i)).rev().enumerate() {
243         assert_eq!(i.get(), index);
244     }
245     assert_eq!(i.get(), 5);
246 }
247 
248 // This test does not work on targets without panic=unwind support.
249 // To work around this problem, test is marked is should_panic, so it will
250 // be automagically skipped on unsuitable targets, such as
251 // wasm32-unknown-unkown.
252 //
253 // It means that we use panic for indicating success.
254 #[test]
255 #[should_panic(expected = "test succeeded")]
array_default_impl_avoids_leaks_on_panic()256 fn array_default_impl_avoids_leaks_on_panic() {
257     use core::sync::atomic::{AtomicUsize, Ordering::Relaxed};
258     static COUNTER: AtomicUsize = AtomicUsize::new(0);
259     #[derive(Debug)]
260     struct Bomb(usize);
261 
262     impl Default for Bomb {
263         fn default() -> Bomb {
264             if COUNTER.load(Relaxed) == 3 {
265                 panic!("bomb limit exceeded");
266             }
267 
268             COUNTER.fetch_add(1, Relaxed);
269             Bomb(COUNTER.load(Relaxed))
270         }
271     }
272 
273     impl Drop for Bomb {
274         fn drop(&mut self) {
275             COUNTER.fetch_sub(1, Relaxed);
276         }
277     }
278 
279     let res = std::panic::catch_unwind(|| <[Bomb; 5]>::default());
280     let panic_msg = match res {
281         Ok(_) => unreachable!(),
282         Err(p) => p.downcast::<&'static str>().unwrap(),
283     };
284     assert_eq!(*panic_msg, "bomb limit exceeded");
285     // check that all bombs are successfully dropped
286     assert_eq!(COUNTER.load(Relaxed), 0);
287     panic!("test succeeded")
288 }
289 
290 #[test]
empty_array_is_always_default()291 fn empty_array_is_always_default() {
292     struct DoesNotImplDefault;
293 
294     let _arr = <[DoesNotImplDefault; 0]>::default();
295 }
296 
297 #[test]
array_map()298 fn array_map() {
299     let a = [1, 2, 3];
300     let b = a.map(|v| v + 1);
301     assert_eq!(b, [2, 3, 4]);
302 
303     let a = [1u8, 2, 3];
304     let b = a.map(|v| v as u64);
305     assert_eq!(b, [1, 2, 3]);
306 }
307 
308 // See note on above test for why `should_panic` is used.
309 #[test]
310 #[should_panic(expected = "test succeeded")]
array_map_drop_safety()311 fn array_map_drop_safety() {
312     static DROPPED: AtomicUsize = AtomicUsize::new(0);
313     struct DropCounter;
314     impl Drop for DropCounter {
315         fn drop(&mut self) {
316             DROPPED.fetch_add(1, Ordering::SeqCst);
317         }
318     }
319 
320     let num_to_create = 5;
321     let success = std::panic::catch_unwind(|| {
322         let items = [0; 10];
323         let mut nth = 0;
324         items.map(|_| {
325             assert!(nth < num_to_create);
326             nth += 1;
327             DropCounter
328         });
329     });
330     assert!(success.is_err());
331     assert_eq!(DROPPED.load(Ordering::SeqCst), num_to_create);
332     panic!("test succeeded")
333 }
334 
335 #[test]
cell_allows_array_cycle()336 fn cell_allows_array_cycle() {
337     use core::cell::Cell;
338 
339     #[derive(Debug)]
340     struct B<'a> {
341         a: [Cell<Option<&'a B<'a>>>; 2],
342     }
343 
344     impl<'a> B<'a> {
345         fn new() -> B<'a> {
346             B { a: [Cell::new(None), Cell::new(None)] }
347         }
348     }
349 
350     let b1 = B::new();
351     let b2 = B::new();
352     let b3 = B::new();
353 
354     b1.a[0].set(Some(&b2));
355     b1.a[1].set(Some(&b3));
356 
357     b2.a[0].set(Some(&b2));
358     b2.a[1].set(Some(&b3));
359 
360     b3.a[0].set(Some(&b1));
361     b3.a[1].set(Some(&b2));
362 }
363 
364 #[test]
array_from_fn()365 fn array_from_fn() {
366     let array = core::array::from_fn(|idx| idx);
367     assert_eq!(array, [0, 1, 2, 3, 4]);
368 }
369 
370 #[test]
array_try_from_fn()371 fn array_try_from_fn() {
372     #[derive(Debug, PartialEq)]
373     enum SomeError {
374         Foo,
375     }
376 
377     let array = core::array::try_from_fn(|i| Ok::<_, SomeError>(i));
378     assert_eq!(array, Ok([0, 1, 2, 3, 4]));
379 
380     let another_array = core::array::try_from_fn::<SomeError, _, (), 2>(|_| Err(SomeError::Foo));
381     assert_eq!(another_array, Err(SomeError::Foo));
382 }
383 
384 #[cfg(not(panic = "abort"))]
385 #[test]
array_try_from_fn_drops_inserted_elements_on_err()386 fn array_try_from_fn_drops_inserted_elements_on_err() {
387     static DROP_COUNTER: AtomicUsize = AtomicUsize::new(0);
388 
389     struct CountDrop;
390     impl Drop for CountDrop {
391         fn drop(&mut self) {
392             DROP_COUNTER.fetch_add(1, Ordering::SeqCst);
393         }
394     }
395 
396     let _ = catch_unwind_silent(move || {
397         let _: Result<[CountDrop; 4], ()> = core::array::try_from_fn(|idx| {
398             if idx == 2 {
399                 return Err(());
400             }
401             Ok(CountDrop)
402         });
403     });
404 
405     assert_eq!(DROP_COUNTER.load(Ordering::SeqCst), 2);
406 }
407 
408 #[cfg(not(panic = "abort"))]
409 #[test]
array_try_from_fn_drops_inserted_elements_on_panic()410 fn array_try_from_fn_drops_inserted_elements_on_panic() {
411     static DROP_COUNTER: AtomicUsize = AtomicUsize::new(0);
412 
413     struct CountDrop;
414     impl Drop for CountDrop {
415         fn drop(&mut self) {
416             DROP_COUNTER.fetch_add(1, Ordering::SeqCst);
417         }
418     }
419 
420     let _ = catch_unwind_silent(move || {
421         let _: Result<[CountDrop; 4], ()> = core::array::try_from_fn(|idx| {
422             if idx == 2 {
423                 panic!("peek a boo");
424             }
425             Ok(CountDrop)
426         });
427     });
428 
429     assert_eq!(DROP_COUNTER.load(Ordering::SeqCst), 2);
430 }
431 
432 #[cfg(not(panic = "abort"))]
433 // https://stackoverflow.com/a/59211505
catch_unwind_silent<F, R>(f: F) -> std::thread::Result<R> where F: FnOnce() -> R + core::panic::UnwindSafe,434 fn catch_unwind_silent<F, R>(f: F) -> std::thread::Result<R>
435 where
436     F: FnOnce() -> R + core::panic::UnwindSafe,
437 {
438     let prev_hook = std::panic::take_hook();
439     std::panic::set_hook(Box::new(|_| {}));
440     let result = std::panic::catch_unwind(f);
441     std::panic::set_hook(prev_hook);
442     result
443 }
444 
445 #[test]
array_split_array_mut()446 fn array_split_array_mut() {
447     let mut v = [1, 2, 3, 4, 5, 6];
448 
449     {
450         let (left, right) = v.split_array_mut::<0>();
451         assert_eq!(left, &mut []);
452         assert_eq!(right, &mut [1, 2, 3, 4, 5, 6]);
453     }
454 
455     {
456         let (left, right) = v.split_array_mut::<6>();
457         assert_eq!(left, &mut [1, 2, 3, 4, 5, 6]);
458         assert_eq!(right, &mut []);
459     }
460 }
461 
462 #[should_panic]
463 #[test]
array_split_array_ref_out_of_bounds()464 fn array_split_array_ref_out_of_bounds() {
465     let v = [1, 2, 3, 4, 5, 6];
466 
467     v.split_array_ref::<7>();
468 }
469 
470 #[should_panic]
471 #[test]
array_split_array_mut_out_of_bounds()472 fn array_split_array_mut_out_of_bounds() {
473     let mut v = [1, 2, 3, 4, 5, 6];
474 
475     v.split_array_mut::<7>();
476 }
477