blob: 1cfb4fd9fd186e55cc84c3b641bdf37e10858d6e [file] [log] [blame]
use core::mem::*;
use core::ptr;
#[cfg(panic = "unwind")]
use std::rc::Rc;
#[test]
fn size_of_basic() {
assert_eq!(size_of::<u8>(), 1);
assert_eq!(size_of::<u16>(), 2);
assert_eq!(size_of::<u32>(), 4);
assert_eq!(size_of::<u64>(), 8);
}
#[test]
#[cfg(target_pointer_width = "16")]
fn size_of_16() {
assert_eq!(size_of::<usize>(), 2);
assert_eq!(size_of::<*const usize>(), 2);
}
#[test]
#[cfg(target_pointer_width = "32")]
fn size_of_32() {
assert_eq!(size_of::<usize>(), 4);
assert_eq!(size_of::<*const usize>(), 4);
}
#[test]
#[cfg(target_pointer_width = "64")]
fn size_of_64() {
assert_eq!(size_of::<usize>(), 8);
assert_eq!(size_of::<*const usize>(), 8);
}
#[test]
fn size_of_val_basic() {
assert_eq!(size_of_val(&1u8), 1);
assert_eq!(size_of_val(&1u16), 2);
assert_eq!(size_of_val(&1u32), 4);
assert_eq!(size_of_val(&1u64), 8);
}
#[test]
fn align_of_basic() {
assert_eq!(align_of::<u8>(), 1);
assert_eq!(align_of::<u16>(), 2);
assert_eq!(align_of::<u32>(), 4);
}
#[test]
#[cfg(target_pointer_width = "16")]
fn align_of_16() {
assert_eq!(align_of::<usize>(), 2);
assert_eq!(align_of::<*const usize>(), 2);
}
#[test]
#[cfg(target_pointer_width = "32")]
fn align_of_32() {
assert_eq!(align_of::<usize>(), 4);
assert_eq!(align_of::<*const usize>(), 4);
}
#[test]
#[cfg(target_pointer_width = "64")]
fn align_of_64() {
assert_eq!(align_of::<usize>(), 8);
assert_eq!(align_of::<*const usize>(), 8);
}
#[test]
fn align_of_val_basic() {
assert_eq!(align_of_val(&1u8), 1);
assert_eq!(align_of_val(&1u16), 2);
assert_eq!(align_of_val(&1u32), 4);
}
#[test]
#[cfg(not(bootstrap))] // stage 0 doesn't have the fix yet, so the test fails
fn align_of_val_raw_packed() {
#[repr(C, packed)]
struct B {
f: [u32],
}
let storage = [0u8; 4];
let b: *const B = ptr::from_raw_parts(storage.as_ptr().cast(), 1);
assert_eq!(unsafe { align_of_val_raw(b) }, 1);
const ALIGN_OF_VAL_RAW: usize = {
let storage = [0u8; 4];
let b: *const B = ptr::from_raw_parts(storage.as_ptr().cast(), 1);
unsafe { align_of_val_raw(b) }
};
assert_eq!(ALIGN_OF_VAL_RAW, 1);
}
#[test]
fn test_swap() {
let mut x = 31337;
let mut y = 42;
swap(&mut x, &mut y);
assert_eq!(x, 42);
assert_eq!(y, 31337);
}
#[test]
fn test_replace() {
let mut x = Some("test".to_string());
let y = replace(&mut x, None);
assert!(x.is_none());
assert!(y.is_some());
}
#[test]
fn test_transmute_copy() {
assert_eq!(1, unsafe { transmute_copy(&1) });
}
#[test]
fn test_transmute_copy_shrink() {
assert_eq!(0_u8, unsafe { transmute_copy(&0_u64) });
}
#[test]
fn test_transmute_copy_unaligned() {
#[repr(C)]
#[derive(Default)]
struct Unaligned {
a: u8,
b: [u8; 8],
}
let u = Unaligned::default();
assert_eq!(0_u64, unsafe { transmute_copy(&u.b) });
}
#[test]
#[cfg(panic = "unwind")]
fn test_transmute_copy_grow_panics() {
use std::panic;
let err = panic::catch_unwind(panic::AssertUnwindSafe(|| unsafe {
let _unused: u64 = transmute_copy(&1_u8);
}));
match err {
Ok(_) => unreachable!(),
Err(payload) => {
payload
.downcast::<&'static str>()
.and_then(|s| {
if *s == "cannot transmute_copy if Dst is larger than Src" {
Ok(s)
} else {
Err(s)
}
})
.unwrap_or_else(|p| panic::resume_unwind(p));
}
}
}
#[test]
#[allow(dead_code)]
fn test_discriminant_send_sync() {
enum Regular {
A,
B(i32),
}
enum NotSendSync {
A(*const i32),
}
fn is_send_sync<T: Send + Sync>() {}
is_send_sync::<Discriminant<Regular>>();
is_send_sync::<Discriminant<NotSendSync>>();
}
#[test]
fn assume_init_good() {
const TRUE: bool = unsafe { MaybeUninit::<bool>::new(true).assume_init() };
assert!(TRUE);
}
#[test]
fn uninit_array_assume_init() {
let mut array = [MaybeUninit::<i16>::uninit(); 5];
array[0].write(3);
array[1].write(1);
array[2].write(4);
array[3].write(1);
array[4].write(5);
let array = unsafe { array.transpose().assume_init() };
assert_eq!(array, [3, 1, 4, 1, 5]);
let [] = unsafe { [MaybeUninit::<!>::uninit(); 0].transpose().assume_init() };
}
#[test]
fn uninit_write_slice() {
let mut dst = [MaybeUninit::new(255); 64];
let src = [0; 64];
assert_eq!(MaybeUninit::write_slice(&mut dst, &src), &src);
}
#[test]
#[should_panic(expected = "source slice length (32) does not match destination slice length (64)")]
fn uninit_write_slice_panic_lt() {
let mut dst = [MaybeUninit::uninit(); 64];
let src = [0; 32];
MaybeUninit::write_slice(&mut dst, &src);
}
#[test]
#[should_panic(expected = "source slice length (128) does not match destination slice length (64)")]
fn uninit_write_slice_panic_gt() {
let mut dst = [MaybeUninit::uninit(); 64];
let src = [0; 128];
MaybeUninit::write_slice(&mut dst, &src);
}
#[test]
fn uninit_clone_from_slice() {
let mut dst = [MaybeUninit::new(255); 64];
let src = [0; 64];
assert_eq!(MaybeUninit::write_slice_cloned(&mut dst, &src), &src);
}
#[test]
#[should_panic(expected = "destination and source slices have different lengths")]
fn uninit_write_slice_cloned_panic_lt() {
let mut dst = [MaybeUninit::uninit(); 64];
let src = [0; 32];
MaybeUninit::write_slice_cloned(&mut dst, &src);
}
#[test]
#[should_panic(expected = "destination and source slices have different lengths")]
fn uninit_write_slice_cloned_panic_gt() {
let mut dst = [MaybeUninit::uninit(); 64];
let src = [0; 128];
MaybeUninit::write_slice_cloned(&mut dst, &src);
}
#[test]
#[cfg(panic = "unwind")]
fn uninit_write_slice_cloned_mid_panic() {
use std::panic;
enum IncrementOrPanic {
Increment(Rc<()>),
ExpectedPanic,
UnexpectedPanic,
}
impl Clone for IncrementOrPanic {
fn clone(&self) -> Self {
match self {
Self::Increment(rc) => Self::Increment(rc.clone()),
Self::ExpectedPanic => panic!("expected panic on clone"),
Self::UnexpectedPanic => panic!("unexpected panic on clone"),
}
}
}
let rc = Rc::new(());
let mut dst = [
MaybeUninit::uninit(),
MaybeUninit::uninit(),
MaybeUninit::uninit(),
MaybeUninit::uninit(),
];
let src = [
IncrementOrPanic::Increment(rc.clone()),
IncrementOrPanic::Increment(rc.clone()),
IncrementOrPanic::ExpectedPanic,
IncrementOrPanic::UnexpectedPanic,
];
let err = panic::catch_unwind(panic::AssertUnwindSafe(|| {
MaybeUninit::write_slice_cloned(&mut dst, &src);
}));
drop(src);
match err {
Ok(_) => unreachable!(),
Err(payload) => {
payload
.downcast::<&'static str>()
.and_then(|s| if *s == "expected panic on clone" { Ok(s) } else { Err(s) })
.unwrap_or_else(|p| panic::resume_unwind(p));
assert_eq!(Rc::strong_count(&rc), 1)
}
}
}
#[test]
fn uninit_write_slice_cloned_no_drop() {
#[derive(Clone)]
struct Bomb;
impl Drop for Bomb {
fn drop(&mut self) {
panic!("dropped a bomb! kaboom")
}
}
let mut dst = [MaybeUninit::uninit()];
let src = [Bomb];
MaybeUninit::write_slice_cloned(&mut dst, &src);
forget(src);
}
#[test]
fn uninit_const_assume_init_read() {
const FOO: u32 = unsafe { MaybeUninit::new(42).assume_init_read() };
assert_eq!(FOO, 42);
}
#[test]
fn const_maybe_uninit() {
use std::ptr;
#[derive(Debug, PartialEq)]
struct Foo {
x: u8,
y: u8,
}
const FIELD_BY_FIELD: Foo = unsafe {
let mut val = MaybeUninit::uninit();
init_y(&mut val); // order shouldn't matter
init_x(&mut val);
val.assume_init()
};
const fn init_x(foo: &mut MaybeUninit<Foo>) {
unsafe {
*ptr::addr_of_mut!((*foo.as_mut_ptr()).x) = 1;
}
}
const fn init_y(foo: &mut MaybeUninit<Foo>) {
unsafe {
*ptr::addr_of_mut!((*foo.as_mut_ptr()).y) = 2;
}
}
assert_eq!(FIELD_BY_FIELD, Foo { x: 1, y: 2 });
}