]> git.lizzy.rs Git - rust.git/blob - library/core/tests/mem.rs
Rollup merge of #103554 - notriddle:notriddle/summary-focus-visible, r=jsha
[rust.git] / library / core / tests / mem.rs
1 use core::mem::*;
2
3 #[cfg(panic = "unwind")]
4 use std::rc::Rc;
5
6 #[test]
7 fn size_of_basic() {
8     assert_eq!(size_of::<u8>(), 1);
9     assert_eq!(size_of::<u16>(), 2);
10     assert_eq!(size_of::<u32>(), 4);
11     assert_eq!(size_of::<u64>(), 8);
12 }
13
14 #[test]
15 #[cfg(target_pointer_width = "16")]
16 fn size_of_16() {
17     assert_eq!(size_of::<usize>(), 2);
18     assert_eq!(size_of::<*const usize>(), 2);
19 }
20
21 #[test]
22 #[cfg(target_pointer_width = "32")]
23 fn size_of_32() {
24     assert_eq!(size_of::<usize>(), 4);
25     assert_eq!(size_of::<*const usize>(), 4);
26 }
27
28 #[test]
29 #[cfg(target_pointer_width = "64")]
30 fn size_of_64() {
31     assert_eq!(size_of::<usize>(), 8);
32     assert_eq!(size_of::<*const usize>(), 8);
33 }
34
35 #[test]
36 fn size_of_val_basic() {
37     assert_eq!(size_of_val(&1u8), 1);
38     assert_eq!(size_of_val(&1u16), 2);
39     assert_eq!(size_of_val(&1u32), 4);
40     assert_eq!(size_of_val(&1u64), 8);
41 }
42
43 #[test]
44 fn align_of_basic() {
45     assert_eq!(align_of::<u8>(), 1);
46     assert_eq!(align_of::<u16>(), 2);
47     assert_eq!(align_of::<u32>(), 4);
48 }
49
50 #[test]
51 #[cfg(target_pointer_width = "16")]
52 fn align_of_16() {
53     assert_eq!(align_of::<usize>(), 2);
54     assert_eq!(align_of::<*const usize>(), 2);
55 }
56
57 #[test]
58 #[cfg(target_pointer_width = "32")]
59 fn align_of_32() {
60     assert_eq!(align_of::<usize>(), 4);
61     assert_eq!(align_of::<*const usize>(), 4);
62 }
63
64 #[test]
65 #[cfg(target_pointer_width = "64")]
66 fn align_of_64() {
67     assert_eq!(align_of::<usize>(), 8);
68     assert_eq!(align_of::<*const usize>(), 8);
69 }
70
71 #[test]
72 fn align_of_val_basic() {
73     assert_eq!(align_of_val(&1u8), 1);
74     assert_eq!(align_of_val(&1u16), 2);
75     assert_eq!(align_of_val(&1u32), 4);
76 }
77
78 #[test]
79 fn test_swap() {
80     let mut x = 31337;
81     let mut y = 42;
82     swap(&mut x, &mut y);
83     assert_eq!(x, 42);
84     assert_eq!(y, 31337);
85 }
86
87 #[test]
88 fn test_replace() {
89     let mut x = Some("test".to_string());
90     let y = replace(&mut x, None);
91     assert!(x.is_none());
92     assert!(y.is_some());
93 }
94
95 #[test]
96 fn test_transmute_copy() {
97     assert_eq!(1, unsafe { transmute_copy(&1) });
98 }
99
100 #[test]
101 fn test_transmute_copy_shrink() {
102     assert_eq!(0_u8, unsafe { transmute_copy(&0_u64) });
103 }
104
105 #[test]
106 fn test_transmute_copy_unaligned() {
107     #[repr(C)]
108     #[derive(Default)]
109     struct Unaligned {
110         a: u8,
111         b: [u8; 8],
112     }
113
114     let u = Unaligned::default();
115     assert_eq!(0_u64, unsafe { transmute_copy(&u.b) });
116 }
117
118 #[test]
119 #[cfg(panic = "unwind")]
120 fn test_transmute_copy_grow_panics() {
121     use std::panic;
122
123     let err = panic::catch_unwind(panic::AssertUnwindSafe(|| unsafe {
124         let _unused: u64 = transmute_copy(&1_u8);
125     }));
126
127     match err {
128         Ok(_) => unreachable!(),
129         Err(payload) => {
130             payload
131                 .downcast::<&'static str>()
132                 .and_then(|s| {
133                     if *s == "cannot transmute_copy if Dst is larger than Src" {
134                         Ok(s)
135                     } else {
136                         Err(s)
137                     }
138                 })
139                 .unwrap_or_else(|p| panic::resume_unwind(p));
140         }
141     }
142 }
143
144 #[test]
145 #[allow(dead_code)]
146 fn test_discriminant_send_sync() {
147     enum Regular {
148         A,
149         B(i32),
150     }
151     enum NotSendSync {
152         A(*const i32),
153     }
154
155     fn is_send_sync<T: Send + Sync>() {}
156
157     is_send_sync::<Discriminant<Regular>>();
158     is_send_sync::<Discriminant<NotSendSync>>();
159 }
160
161 #[test]
162 fn assume_init_good() {
163     const TRUE: bool = unsafe { MaybeUninit::<bool>::new(true).assume_init() };
164
165     assert!(TRUE);
166 }
167
168 #[test]
169 fn uninit_array_assume_init() {
170     let mut array = [MaybeUninit::<i16>::uninit(); 5];
171     array[0].write(3);
172     array[1].write(1);
173     array[2].write(4);
174     array[3].write(1);
175     array[4].write(5);
176
177     let array = unsafe { array.transpose().assume_init() };
178
179     assert_eq!(array, [3, 1, 4, 1, 5]);
180
181     let [] = unsafe { [MaybeUninit::<!>::uninit(); 0].transpose().assume_init() };
182 }
183
184 #[test]
185 fn uninit_write_slice() {
186     let mut dst = [MaybeUninit::new(255); 64];
187     let src = [0; 64];
188
189     assert_eq!(MaybeUninit::write_slice(&mut dst, &src), &src);
190 }
191
192 #[test]
193 #[should_panic(expected = "source slice length (32) does not match destination slice length (64)")]
194 fn uninit_write_slice_panic_lt() {
195     let mut dst = [MaybeUninit::uninit(); 64];
196     let src = [0; 32];
197
198     MaybeUninit::write_slice(&mut dst, &src);
199 }
200
201 #[test]
202 #[should_panic(expected = "source slice length (128) does not match destination slice length (64)")]
203 fn uninit_write_slice_panic_gt() {
204     let mut dst = [MaybeUninit::uninit(); 64];
205     let src = [0; 128];
206
207     MaybeUninit::write_slice(&mut dst, &src);
208 }
209
210 #[test]
211 fn uninit_clone_from_slice() {
212     let mut dst = [MaybeUninit::new(255); 64];
213     let src = [0; 64];
214
215     assert_eq!(MaybeUninit::write_slice_cloned(&mut dst, &src), &src);
216 }
217
218 #[test]
219 #[should_panic(expected = "destination and source slices have different lengths")]
220 fn uninit_write_slice_cloned_panic_lt() {
221     let mut dst = [MaybeUninit::uninit(); 64];
222     let src = [0; 32];
223
224     MaybeUninit::write_slice_cloned(&mut dst, &src);
225 }
226
227 #[test]
228 #[should_panic(expected = "destination and source slices have different lengths")]
229 fn uninit_write_slice_cloned_panic_gt() {
230     let mut dst = [MaybeUninit::uninit(); 64];
231     let src = [0; 128];
232
233     MaybeUninit::write_slice_cloned(&mut dst, &src);
234 }
235
236 #[test]
237 #[cfg(panic = "unwind")]
238 fn uninit_write_slice_cloned_mid_panic() {
239     use std::panic;
240
241     enum IncrementOrPanic {
242         Increment(Rc<()>),
243         ExpectedPanic,
244         UnexpectedPanic,
245     }
246
247     impl Clone for IncrementOrPanic {
248         fn clone(&self) -> Self {
249             match self {
250                 Self::Increment(rc) => Self::Increment(rc.clone()),
251                 Self::ExpectedPanic => panic!("expected panic on clone"),
252                 Self::UnexpectedPanic => panic!("unexpected panic on clone"),
253             }
254         }
255     }
256
257     let rc = Rc::new(());
258
259     let mut dst = [
260         MaybeUninit::uninit(),
261         MaybeUninit::uninit(),
262         MaybeUninit::uninit(),
263         MaybeUninit::uninit(),
264     ];
265
266     let src = [
267         IncrementOrPanic::Increment(rc.clone()),
268         IncrementOrPanic::Increment(rc.clone()),
269         IncrementOrPanic::ExpectedPanic,
270         IncrementOrPanic::UnexpectedPanic,
271     ];
272
273     let err = panic::catch_unwind(panic::AssertUnwindSafe(|| {
274         MaybeUninit::write_slice_cloned(&mut dst, &src);
275     }));
276
277     drop(src);
278
279     match err {
280         Ok(_) => unreachable!(),
281         Err(payload) => {
282             payload
283                 .downcast::<&'static str>()
284                 .and_then(|s| if *s == "expected panic on clone" { Ok(s) } else { Err(s) })
285                 .unwrap_or_else(|p| panic::resume_unwind(p));
286
287             assert_eq!(Rc::strong_count(&rc), 1)
288         }
289     }
290 }
291
292 #[test]
293 fn uninit_write_slice_cloned_no_drop() {
294     #[derive(Clone)]
295     struct Bomb;
296
297     impl Drop for Bomb {
298         fn drop(&mut self) {
299             panic!("dropped a bomb! kaboom")
300         }
301     }
302
303     let mut dst = [MaybeUninit::uninit()];
304     let src = [Bomb];
305
306     MaybeUninit::write_slice_cloned(&mut dst, &src);
307
308     forget(src);
309 }
310
311 #[test]
312 fn uninit_const_assume_init_read() {
313     const FOO: u32 = unsafe { MaybeUninit::new(42).assume_init_read() };
314     assert_eq!(FOO, 42);
315 }
316
317 #[test]
318 fn const_maybe_uninit() {
319     use std::ptr;
320
321     #[derive(Debug, PartialEq)]
322     struct Foo {
323         x: u8,
324         y: u8,
325     }
326
327     const FIELD_BY_FIELD: Foo = unsafe {
328         let mut val = MaybeUninit::uninit();
329         init_y(&mut val); // order shouldn't matter
330         init_x(&mut val);
331         val.assume_init()
332     };
333
334     const fn init_x(foo: &mut MaybeUninit<Foo>) {
335         unsafe {
336             *ptr::addr_of_mut!((*foo.as_mut_ptr()).x) = 1;
337         }
338     }
339
340     const fn init_y(foo: &mut MaybeUninit<Foo>) {
341         unsafe {
342             *ptr::addr_of_mut!((*foo.as_mut_ptr()).y) = 2;
343         }
344     }
345
346     assert_eq!(FIELD_BY_FIELD, Foo { x: 1, y: 2 });
347 }