]> git.proxmox.com Git - rustc.git/blob - library/core/tests/array.rs
New upstream version 1.63.0+dfsg1
[rustc.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 }