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