]> git.proxmox.com Git - rustc.git/blame - library/core/tests/array.rs
New upstream version 1.58.1+dfsg1
[rustc.git] / library / core / tests / array.rs
CommitLineData
17df50a5 1use core::array;
abe05a73 2use core::convert::TryFrom;
c295e0f8 3use core::sync::atomic::{AtomicUsize, Ordering};
e9174d1e 4
1b1a35ee
XL
5#[test]
6fn 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);
3c0e092e
XL
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]));
1b1a35ee
XL
15}
16
17#[test]
18fn 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
abe05a73
XL
25#[test]
26fn 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}
e74abb32 46
e74abb32
XL
47#[test]
48fn iterator_collect() {
49 let arr = [0, 1, 2, 5, 9];
17df50a5 50 let v: Vec<_> = IntoIterator::into_iter(arr.clone()).collect();
e74abb32
XL
51 assert_eq!(&arr[..], &v[..]);
52}
53
54#[test]
55fn iterator_rev_collect() {
56 let arr = [0, 1, 2, 5, 9];
17df50a5 57 let v: Vec<_> = IntoIterator::into_iter(arr.clone()).rev().collect();
e74abb32
XL
58 assert_eq!(&v[..], &[9, 5, 2, 1, 0]);
59}
60
61#[test]
62fn iterator_nth() {
63 let v = [0, 1, 2, 3, 4];
64 for i in 0..v.len() {
17df50a5 65 assert_eq!(IntoIterator::into_iter(v.clone()).nth(i).unwrap(), v[i]);
e74abb32 66 }
17df50a5 67 assert_eq!(IntoIterator::into_iter(v.clone()).nth(v.len()), None);
e74abb32 68
17df50a5 69 let mut iter = IntoIterator::into_iter(v);
e74abb32
XL
70 assert_eq!(iter.nth(2).unwrap(), v[2]);
71 assert_eq!(iter.nth(1).unwrap(), v[4]);
72}
73
74#[test]
75fn iterator_last() {
76 let v = [0, 1, 2, 3, 4];
17df50a5
XL
77 assert_eq!(IntoIterator::into_iter(v).last().unwrap(), 4);
78 assert_eq!(IntoIterator::into_iter([0]).last().unwrap(), 0);
e74abb32 79
17df50a5 80 let mut it = IntoIterator::into_iter([0, 9, 2, 4]);
e74abb32
XL
81 assert_eq!(it.next_back(), Some(4));
82 assert_eq!(it.last(), Some(2));
83}
84
85#[test]
86fn iterator_clone() {
17df50a5 87 let mut it = IntoIterator::into_iter([0, 2, 4, 6, 8]);
e74abb32
XL
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]
100fn iterator_fused() {
17df50a5 101 let mut it = IntoIterator::into_iter([0, 9, 2]);
e74abb32
XL
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]
113fn iterator_len() {
17df50a5 114 let mut it = IntoIterator::into_iter([0, 1, 2, 5, 9]);
e74abb32
XL
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
17df50a5 130 let it = IntoIterator::into_iter([] as [String; 0]);
e74abb32
XL
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]
137fn iterator_count() {
138 let v = [0, 1, 2, 3, 4];
17df50a5 139 assert_eq!(IntoIterator::into_iter(v.clone()).count(), 5);
e74abb32 140
17df50a5 141 let mut iter2 = IntoIterator::into_iter(v);
e74abb32
XL
142 iter2.next();
143 iter2.next();
144 assert_eq!(iter2.count(), 3);
145}
146
147#[test]
148fn iterator_flat_map() {
17df50a5 149 assert!((0..5).flat_map(|i| IntoIterator::into_iter([2 * i, 2 * i + 1])).eq(0..10));
e74abb32
XL
150}
151
152#[test]
153fn iterator_debug() {
154 let arr = [0, 1, 2, 5, 9];
17df50a5 155 assert_eq!(format!("{:?}", IntoIterator::into_iter(arr)), "IntoIter([0, 1, 2, 5, 9])",);
e74abb32
XL
156}
157
158#[test]
159fn 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<'_> {
60c5eb7d 170 fn drop(&mut self) {
e74abb32
XL
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 {
17df50a5 185 IntoIterator::into_iter(five(&i));
e74abb32
XL
186 }
187 assert_eq!(i.get(), 5);
188
189 // Call `next()` once.
190 let i = Cell::new(0);
191 {
17df50a5 192 let mut iter = IntoIterator::into_iter(five(&i));
e74abb32
XL
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 {
17df50a5 203 let mut iter = IntoIterator::into_iter(five(&i));
e74abb32
XL
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 {
17df50a5 226 let mut iter = IntoIterator::into_iter(five(&i));
e74abb32
XL
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);
17df50a5 236 for (index, _x) in IntoIterator::into_iter(five(&i)).enumerate() {
e74abb32
XL
237 assert_eq!(i.get(), index);
238 }
239 assert_eq!(i.get(), 5);
240
241 let i = Cell::new(0);
17df50a5 242 for (index, _x) in IntoIterator::into_iter(five(&i)).rev().enumerate() {
e74abb32
XL
243 assert_eq!(i.get(), index);
244 }
245 assert_eq!(i.get(), 5);
246}
f035d41b
XL
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")]
256fn 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]
291fn empty_array_is_always_default() {
292 struct DoesNotImplDefault;
293
294 let _arr = <[DoesNotImplDefault; 0]>::default();
295}
3dfed10e
XL
296
297#[test]
298fn 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")]
311fn array_map_drop_safety() {
3dfed10e
XL
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}
1b1a35ee
XL
334
335#[test]
336fn 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}
c295e0f8
XL
363
364#[test]
365fn 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]
371fn 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]
386fn 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]
410fn 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
434fn catch_unwind_silent<F, R>(f: F) -> std::thread::Result<R>
435where
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}
3c0e092e
XL
444
445#[test]
446fn 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]
464fn 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]
472fn 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}