]> git.lizzy.rs Git - rust.git/blob - library/core/tests/array.rs
Auto merge of #106975 - tmiasko:basic-blocks-cache, r=cjgillot
[rust.git] / library / core / tests / array.rs
1 use core::array;
2 use core::convert::TryFrom;
3 use core::sync::atomic::{AtomicUsize, Ordering};
4
5 #[test]
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]
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]
26 fn array_try_from() {
27     macro_rules! test {
28         ($($N:expr)+) => {
29             $({
30                 type Array = [u8; $N];
31                 let mut 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                 let result = <Array>::try_from(slice);
38                 assert_eq!(&array, &result.unwrap());
39
40                 let mut_slice: &mut [u8] = &mut array[..];
41                 let result = <&mut Array>::try_from(mut_slice);
42                 assert_eq!(&[0; $N], result.unwrap());
43
44                 let mut_slice: &mut [u8] = &mut array[..];
45                 let result = <Array>::try_from(mut_slice);
46                 assert_eq!(&array, &result.unwrap());
47             })+
48         }
49     }
50     test! {
51          0  1  2  3  4  5  6  7  8  9
52         10 11 12 13 14 15 16 17 18 19
53         20 21 22 23 24 25 26 27 28 29
54         30 31 32
55     }
56 }
57
58 #[test]
59 fn iterator_collect() {
60     let arr = [0, 1, 2, 5, 9];
61     let v: Vec<_> = IntoIterator::into_iter(arr.clone()).collect();
62     assert_eq!(&arr[..], &v[..]);
63 }
64
65 #[test]
66 fn iterator_rev_collect() {
67     let arr = [0, 1, 2, 5, 9];
68     let v: Vec<_> = IntoIterator::into_iter(arr.clone()).rev().collect();
69     assert_eq!(&v[..], &[9, 5, 2, 1, 0]);
70 }
71
72 #[test]
73 fn iterator_nth() {
74     let v = [0, 1, 2, 3, 4];
75     for i in 0..v.len() {
76         assert_eq!(IntoIterator::into_iter(v.clone()).nth(i).unwrap(), v[i]);
77     }
78     assert_eq!(IntoIterator::into_iter(v.clone()).nth(v.len()), None);
79
80     let mut iter = IntoIterator::into_iter(v);
81     assert_eq!(iter.nth(2).unwrap(), v[2]);
82     assert_eq!(iter.nth(1).unwrap(), v[4]);
83 }
84
85 #[test]
86 fn iterator_last() {
87     let v = [0, 1, 2, 3, 4];
88     assert_eq!(IntoIterator::into_iter(v).last().unwrap(), 4);
89     assert_eq!(IntoIterator::into_iter([0]).last().unwrap(), 0);
90
91     let mut it = IntoIterator::into_iter([0, 9, 2, 4]);
92     assert_eq!(it.next_back(), Some(4));
93     assert_eq!(it.last(), Some(2));
94 }
95
96 #[test]
97 fn iterator_clone() {
98     let mut it = IntoIterator::into_iter([0, 2, 4, 6, 8]);
99     assert_eq!(it.next(), Some(0));
100     assert_eq!(it.next_back(), Some(8));
101     let mut clone = it.clone();
102     assert_eq!(it.next_back(), Some(6));
103     assert_eq!(clone.next_back(), Some(6));
104     assert_eq!(it.next_back(), Some(4));
105     assert_eq!(clone.next_back(), Some(4));
106     assert_eq!(it.next(), Some(2));
107     assert_eq!(clone.next(), Some(2));
108 }
109
110 #[test]
111 fn iterator_fused() {
112     let mut it = IntoIterator::into_iter([0, 9, 2]);
113     assert_eq!(it.next(), Some(0));
114     assert_eq!(it.next(), Some(9));
115     assert_eq!(it.next(), Some(2));
116     assert_eq!(it.next(), None);
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 }
122
123 #[test]
124 fn iterator_len() {
125     let mut it = IntoIterator::into_iter([0, 1, 2, 5, 9]);
126     assert_eq!(it.size_hint(), (5, Some(5)));
127     assert_eq!(it.len(), 5);
128     assert_eq!(it.is_empty(), false);
129
130     assert_eq!(it.next(), Some(0));
131     assert_eq!(it.size_hint(), (4, Some(4)));
132     assert_eq!(it.len(), 4);
133     assert_eq!(it.is_empty(), false);
134
135     assert_eq!(it.next_back(), Some(9));
136     assert_eq!(it.size_hint(), (3, Some(3)));
137     assert_eq!(it.len(), 3);
138     assert_eq!(it.is_empty(), false);
139
140     // Empty
141     let it = IntoIterator::into_iter([] as [String; 0]);
142     assert_eq!(it.size_hint(), (0, Some(0)));
143     assert_eq!(it.len(), 0);
144     assert_eq!(it.is_empty(), true);
145 }
146
147 #[test]
148 fn iterator_count() {
149     let v = [0, 1, 2, 3, 4];
150     assert_eq!(IntoIterator::into_iter(v.clone()).count(), 5);
151
152     let mut iter2 = IntoIterator::into_iter(v);
153     iter2.next();
154     iter2.next();
155     assert_eq!(iter2.count(), 3);
156 }
157
158 #[test]
159 fn iterator_flat_map() {
160     assert!((0..5).flat_map(|i| IntoIterator::into_iter([2 * i, 2 * i + 1])).eq(0..10));
161 }
162
163 #[test]
164 fn iterator_debug() {
165     let arr = [0, 1, 2, 5, 9];
166     assert_eq!(format!("{:?}", IntoIterator::into_iter(arr)), "IntoIter([0, 1, 2, 5, 9])",);
167 }
168
169 #[test]
170 fn iterator_drops() {
171     use core::cell::Cell;
172
173     // This test makes sure the correct number of elements are dropped. The `R`
174     // type is just a reference to a `Cell` that is incremented when an `R` is
175     // dropped.
176
177     #[derive(Clone)]
178     struct Foo<'a>(&'a Cell<usize>);
179
180     impl Drop for Foo<'_> {
181         fn drop(&mut self) {
182             self.0.set(self.0.get() + 1);
183         }
184     }
185
186     fn five(i: &Cell<usize>) -> [Foo<'_>; 5] {
187         // This is somewhat verbose because `Foo` does not implement `Copy`
188         // since it implements `Drop`. Consequently, we cannot write
189         // `[Foo(i); 5]`.
190         [Foo(i), Foo(i), Foo(i), Foo(i), Foo(i)]
191     }
192
193     // Simple: drop new iterator.
194     let i = Cell::new(0);
195     {
196         IntoIterator::into_iter(five(&i));
197     }
198     assert_eq!(i.get(), 5);
199
200     // Call `next()` once.
201     let i = Cell::new(0);
202     {
203         let mut iter = IntoIterator::into_iter(five(&i));
204         let _x = iter.next();
205         assert_eq!(i.get(), 0);
206         assert_eq!(iter.count(), 4);
207         assert_eq!(i.get(), 4);
208     }
209     assert_eq!(i.get(), 5);
210
211     // Check `clone` and calling `next`/`next_back`.
212     let i = Cell::new(0);
213     {
214         let mut iter = IntoIterator::into_iter(five(&i));
215         iter.next();
216         assert_eq!(i.get(), 1);
217         iter.next_back();
218         assert_eq!(i.get(), 2);
219
220         let mut clone = iter.clone();
221         assert_eq!(i.get(), 2);
222
223         iter.next();
224         assert_eq!(i.get(), 3);
225
226         clone.next();
227         assert_eq!(i.get(), 4);
228
229         assert_eq!(clone.count(), 2);
230         assert_eq!(i.get(), 6);
231     }
232     assert_eq!(i.get(), 8);
233
234     // Check via `nth`.
235     let i = Cell::new(0);
236     {
237         let mut iter = IntoIterator::into_iter(five(&i));
238         let _x = iter.nth(2);
239         assert_eq!(i.get(), 2);
240         let _y = iter.last();
241         assert_eq!(i.get(), 3);
242     }
243     assert_eq!(i.get(), 5);
244
245     // Check every element.
246     let i = Cell::new(0);
247     for (index, _x) in IntoIterator::into_iter(five(&i)).enumerate() {
248         assert_eq!(i.get(), index);
249     }
250     assert_eq!(i.get(), 5);
251
252     let i = Cell::new(0);
253     for (index, _x) in IntoIterator::into_iter(five(&i)).rev().enumerate() {
254         assert_eq!(i.get(), index);
255     }
256     assert_eq!(i.get(), 5);
257 }
258
259 // This test does not work on targets without panic=unwind support.
260 // To work around this problem, test is marked is should_panic, so it will
261 // be automagically skipped on unsuitable targets, such as
262 // wasm32-unknown-unknown.
263 //
264 // It means that we use panic for indicating success.
265 #[test]
266 #[should_panic(expected = "test succeeded")]
267 fn array_default_impl_avoids_leaks_on_panic() {
268     use core::sync::atomic::{AtomicUsize, Ordering::Relaxed};
269     static COUNTER: AtomicUsize = AtomicUsize::new(0);
270     #[derive(Debug)]
271     struct Bomb(usize);
272
273     impl Default for Bomb {
274         fn default() -> Bomb {
275             if COUNTER.load(Relaxed) == 3 {
276                 panic!("bomb limit exceeded");
277             }
278
279             COUNTER.fetch_add(1, Relaxed);
280             Bomb(COUNTER.load(Relaxed))
281         }
282     }
283
284     impl Drop for Bomb {
285         fn drop(&mut self) {
286             COUNTER.fetch_sub(1, Relaxed);
287         }
288     }
289
290     let res = std::panic::catch_unwind(|| <[Bomb; 5]>::default());
291     let panic_msg = match res {
292         Ok(_) => unreachable!(),
293         Err(p) => p.downcast::<&'static str>().unwrap(),
294     };
295     assert_eq!(*panic_msg, "bomb limit exceeded");
296     // check that all bombs are successfully dropped
297     assert_eq!(COUNTER.load(Relaxed), 0);
298     panic!("test succeeded")
299 }
300
301 #[test]
302 fn empty_array_is_always_default() {
303     struct DoesNotImplDefault;
304
305     let _arr = <[DoesNotImplDefault; 0]>::default();
306 }
307
308 #[test]
309 fn array_map() {
310     let a = [1, 2, 3];
311     let b = a.map(|v| v + 1);
312     assert_eq!(b, [2, 3, 4]);
313
314     let a = [1u8, 2, 3];
315     let b = a.map(|v| v as u64);
316     assert_eq!(b, [1, 2, 3]);
317 }
318
319 // See note on above test for why `should_panic` is used.
320 #[test]
321 #[should_panic(expected = "test succeeded")]
322 fn array_map_drop_safety() {
323     static DROPPED: AtomicUsize = AtomicUsize::new(0);
324     struct DropCounter;
325     impl Drop for DropCounter {
326         fn drop(&mut self) {
327             DROPPED.fetch_add(1, Ordering::SeqCst);
328         }
329     }
330
331     let num_to_create = 5;
332     let success = std::panic::catch_unwind(|| {
333         let items = [0; 10];
334         let mut nth = 0;
335         items.map(|_| {
336             assert!(nth < num_to_create);
337             nth += 1;
338             DropCounter
339         });
340     });
341     assert!(success.is_err());
342     assert_eq!(DROPPED.load(Ordering::SeqCst), num_to_create);
343     panic!("test succeeded")
344 }
345
346 #[test]
347 fn cell_allows_array_cycle() {
348     use core::cell::Cell;
349
350     #[derive(Debug)]
351     struct B<'a> {
352         a: [Cell<Option<&'a B<'a>>>; 2],
353     }
354
355     impl<'a> B<'a> {
356         fn new() -> B<'a> {
357             B { a: [Cell::new(None), Cell::new(None)] }
358         }
359     }
360
361     let b1 = B::new();
362     let b2 = B::new();
363     let b3 = B::new();
364
365     b1.a[0].set(Some(&b2));
366     b1.a[1].set(Some(&b3));
367
368     b2.a[0].set(Some(&b2));
369     b2.a[1].set(Some(&b3));
370
371     b3.a[0].set(Some(&b1));
372     b3.a[1].set(Some(&b2));
373 }
374
375 #[test]
376 fn array_from_fn() {
377     let array = core::array::from_fn(|idx| idx);
378     assert_eq!(array, [0, 1, 2, 3, 4]);
379 }
380
381 #[test]
382 fn array_try_from_fn() {
383     #[derive(Debug, PartialEq)]
384     enum SomeError {
385         Foo,
386     }
387
388     let array = core::array::try_from_fn(|i| Ok::<_, SomeError>(i));
389     assert_eq!(array, Ok([0, 1, 2, 3, 4]));
390
391     let another_array = core::array::try_from_fn::<Result<(), _>, 2, _>(|_| Err(SomeError::Foo));
392     assert_eq!(another_array, Err(SomeError::Foo));
393 }
394
395 #[cfg(not(panic = "abort"))]
396 #[test]
397 fn array_try_from_fn_drops_inserted_elements_on_err() {
398     static DROP_COUNTER: AtomicUsize = AtomicUsize::new(0);
399
400     struct CountDrop;
401     impl Drop for CountDrop {
402         fn drop(&mut self) {
403             DROP_COUNTER.fetch_add(1, Ordering::SeqCst);
404         }
405     }
406
407     let _ = catch_unwind_silent(move || {
408         let _: Result<[CountDrop; 4], ()> = core::array::try_from_fn(|idx| {
409             if idx == 2 {
410                 return Err(());
411             }
412             Ok(CountDrop)
413         });
414     });
415
416     assert_eq!(DROP_COUNTER.load(Ordering::SeqCst), 2);
417 }
418
419 #[cfg(not(panic = "abort"))]
420 #[test]
421 fn array_try_from_fn_drops_inserted_elements_on_panic() {
422     static DROP_COUNTER: AtomicUsize = AtomicUsize::new(0);
423
424     struct CountDrop;
425     impl Drop for CountDrop {
426         fn drop(&mut self) {
427             DROP_COUNTER.fetch_add(1, Ordering::SeqCst);
428         }
429     }
430
431     let _ = catch_unwind_silent(move || {
432         let _: Result<[CountDrop; 4], ()> = core::array::try_from_fn(|idx| {
433             if idx == 2 {
434                 panic!("peek a boo");
435             }
436             Ok(CountDrop)
437         });
438     });
439
440     assert_eq!(DROP_COUNTER.load(Ordering::SeqCst), 2);
441 }
442
443 #[cfg(not(panic = "abort"))]
444 // https://stackoverflow.com/a/59211505
445 fn catch_unwind_silent<F, R>(f: F) -> std::thread::Result<R>
446 where
447     F: FnOnce() -> R + core::panic::UnwindSafe,
448 {
449     let prev_hook = std::panic::take_hook();
450     std::panic::set_hook(Box::new(|_| {}));
451     let result = std::panic::catch_unwind(f);
452     std::panic::set_hook(prev_hook);
453     result
454 }
455
456 #[test]
457 fn array_split_array_mut() {
458     let mut v = [1, 2, 3, 4, 5, 6];
459
460     {
461         let (left, right) = v.split_array_mut::<0>();
462         assert_eq!(left, &mut []);
463         assert_eq!(right, &mut [1, 2, 3, 4, 5, 6]);
464     }
465
466     {
467         let (left, right) = v.split_array_mut::<6>();
468         assert_eq!(left, &mut [1, 2, 3, 4, 5, 6]);
469         assert_eq!(right, &mut []);
470     }
471 }
472
473 #[test]
474 fn array_rsplit_array_mut() {
475     let mut v = [1, 2, 3, 4, 5, 6];
476
477     {
478         let (left, right) = v.rsplit_array_mut::<0>();
479         assert_eq!(left, &mut [1, 2, 3, 4, 5, 6]);
480         assert_eq!(right, &mut []);
481     }
482
483     {
484         let (left, right) = v.rsplit_array_mut::<6>();
485         assert_eq!(left, &mut []);
486         assert_eq!(right, &mut [1, 2, 3, 4, 5, 6]);
487     }
488 }
489
490 #[should_panic]
491 #[test]
492 fn array_split_array_ref_out_of_bounds() {
493     let v = [1, 2, 3, 4, 5, 6];
494
495     v.split_array_ref::<7>();
496 }
497
498 #[should_panic]
499 #[test]
500 fn array_split_array_mut_out_of_bounds() {
501     let mut v = [1, 2, 3, 4, 5, 6];
502
503     v.split_array_mut::<7>();
504 }
505
506 #[should_panic]
507 #[test]
508 fn array_rsplit_array_ref_out_of_bounds() {
509     let v = [1, 2, 3, 4, 5, 6];
510
511     v.rsplit_array_ref::<7>();
512 }
513
514 #[should_panic]
515 #[test]
516 fn array_rsplit_array_mut_out_of_bounds() {
517     let mut v = [1, 2, 3, 4, 5, 6];
518
519     v.rsplit_array_mut::<7>();
520 }
521
522 #[test]
523 fn array_intoiter_advance_by() {
524     use std::cell::Cell;
525     struct DropCounter<'a>(usize, &'a Cell<usize>);
526     impl Drop for DropCounter<'_> {
527         fn drop(&mut self) {
528             let x = self.1.get();
529             self.1.set(x + 1);
530         }
531     }
532
533     let counter = Cell::new(0);
534     let a: [_; 100] = std::array::from_fn(|i| DropCounter(i, &counter));
535     let mut it = IntoIterator::into_iter(a);
536
537     let r = it.advance_by(1);
538     assert_eq!(r, Ok(()));
539     assert_eq!(it.len(), 99);
540     assert_eq!(counter.get(), 1);
541
542     let r = it.advance_by(0);
543     assert_eq!(r, Ok(()));
544     assert_eq!(it.len(), 99);
545     assert_eq!(counter.get(), 1);
546
547     let r = it.advance_by(11);
548     assert_eq!(r, Ok(()));
549     assert_eq!(it.len(), 88);
550     assert_eq!(counter.get(), 12);
551
552     let x = it.next();
553     assert_eq!(x.as_ref().map(|x| x.0), Some(12));
554     assert_eq!(it.len(), 87);
555     assert_eq!(counter.get(), 12);
556     drop(x);
557     assert_eq!(counter.get(), 13);
558
559     let r = it.advance_by(123456);
560     assert_eq!(r, Err(87));
561     assert_eq!(it.len(), 0);
562     assert_eq!(counter.get(), 100);
563
564     let r = it.advance_by(0);
565     assert_eq!(r, Ok(()));
566     assert_eq!(it.len(), 0);
567     assert_eq!(counter.get(), 100);
568
569     let r = it.advance_by(10);
570     assert_eq!(r, Err(0));
571     assert_eq!(it.len(), 0);
572     assert_eq!(counter.get(), 100);
573 }
574
575 #[test]
576 fn array_intoiter_advance_back_by() {
577     use std::cell::Cell;
578     struct DropCounter<'a>(usize, &'a Cell<usize>);
579     impl Drop for DropCounter<'_> {
580         fn drop(&mut self) {
581             let x = self.1.get();
582             self.1.set(x + 1);
583         }
584     }
585
586     let counter = Cell::new(0);
587     let a: [_; 100] = std::array::from_fn(|i| DropCounter(i, &counter));
588     let mut it = IntoIterator::into_iter(a);
589
590     let r = it.advance_back_by(1);
591     assert_eq!(r, Ok(()));
592     assert_eq!(it.len(), 99);
593     assert_eq!(counter.get(), 1);
594
595     let r = it.advance_back_by(0);
596     assert_eq!(r, Ok(()));
597     assert_eq!(it.len(), 99);
598     assert_eq!(counter.get(), 1);
599
600     let r = it.advance_back_by(11);
601     assert_eq!(r, Ok(()));
602     assert_eq!(it.len(), 88);
603     assert_eq!(counter.get(), 12);
604
605     let x = it.next_back();
606     assert_eq!(x.as_ref().map(|x| x.0), Some(87));
607     assert_eq!(it.len(), 87);
608     assert_eq!(counter.get(), 12);
609     drop(x);
610     assert_eq!(counter.get(), 13);
611
612     let r = it.advance_back_by(123456);
613     assert_eq!(r, Err(87));
614     assert_eq!(it.len(), 0);
615     assert_eq!(counter.get(), 100);
616
617     let r = it.advance_back_by(0);
618     assert_eq!(r, Ok(()));
619     assert_eq!(it.len(), 0);
620     assert_eq!(counter.get(), 100);
621
622     let r = it.advance_back_by(10);
623     assert_eq!(r, Err(0));
624     assert_eq!(it.len(), 0);
625     assert_eq!(counter.get(), 100);
626 }
627
628 #[test]
629 fn array_mixed_equality_integers() {
630     let array3: [i32; 3] = [1, 2, 3];
631     let array3b: [i32; 3] = [3, 2, 1];
632     let array4: [i32; 4] = [1, 2, 3, 4];
633
634     let slice3: &[i32] = &{ array3 };
635     let slice3b: &[i32] = &{ array3b };
636     let slice4: &[i32] = &{ array4 };
637     assert!(array3 == slice3);
638     assert!(array3 != slice3b);
639     assert!(array3 != slice4);
640     assert!(slice3 == array3);
641     assert!(slice3b != array3);
642     assert!(slice4 != array3);
643
644     let mut3: &mut [i32] = &mut { array3 };
645     let mut3b: &mut [i32] = &mut { array3b };
646     let mut4: &mut [i32] = &mut { array4 };
647     assert!(array3 == mut3);
648     assert!(array3 != mut3b);
649     assert!(array3 != mut4);
650     assert!(mut3 == array3);
651     assert!(mut3b != array3);
652     assert!(mut4 != array3);
653 }
654
655 #[test]
656 fn array_mixed_equality_nans() {
657     let array3: [f32; 3] = [1.0, std::f32::NAN, 3.0];
658
659     let slice3: &[f32] = &{ array3 };
660     assert!(!(array3 == slice3));
661     assert!(array3 != slice3);
662     assert!(!(slice3 == array3));
663     assert!(slice3 != array3);
664
665     let mut3: &mut [f32] = &mut { array3 };
666     assert!(!(array3 == mut3));
667     assert!(array3 != mut3);
668     assert!(!(mut3 == array3));
669     assert!(mut3 != array3);
670 }
671
672 #[test]
673 fn array_into_iter_fold() {
674     // Strings to help MIRI catch if we double-free or something
675     let a = ["Aa".to_string(), "Bb".to_string(), "Cc".to_string()];
676     let mut s = "s".to_string();
677     a.into_iter().for_each(|b| s += &b);
678     assert_eq!(s, "sAaBbCc");
679
680     let a = [1, 2, 3, 4, 5, 6];
681     let mut it = a.into_iter();
682     it.advance_by(1).unwrap();
683     it.advance_back_by(2).unwrap();
684     let s = it.fold(10, |a, b| 10 * a + b);
685     assert_eq!(s, 10234);
686 }
687
688 #[test]
689 fn array_into_iter_rfold() {
690     // Strings to help MIRI catch if we double-free or something
691     let a = ["Aa".to_string(), "Bb".to_string(), "Cc".to_string()];
692     let mut s = "s".to_string();
693     a.into_iter().rev().for_each(|b| s += &b);
694     assert_eq!(s, "sCcBbAa");
695
696     let a = [1, 2, 3, 4, 5, 6];
697     let mut it = a.into_iter();
698     it.advance_by(1).unwrap();
699     it.advance_back_by(2).unwrap();
700     let s = it.rfold(10, |a, b| 10 * a + b);
701     assert_eq!(s, 10432);
702 }