diff options
| author | Simonas Kazlauskas <git@kazlauskas.me> | 2018-04-29 17:09:56 +0300 |
|---|---|---|
| committer | Simonas Kazlauskas <git@kazlauskas.me> | 2018-05-17 23:13:08 +0300 |
| commit | 680031b0164a94aaeee17a1d8c3027e6e8865a4c (patch) | |
| tree | d527dbed79906a163f5949a87debafe8b66ef257 /src/libcore/tests | |
| parent | d45378216b31eab9ee7c7c461ae20bfb29bd20b3 (diff) | |
| download | rust-680031b0164a94aaeee17a1d8c3027e6e8865a4c.tar.gz rust-680031b0164a94aaeee17a1d8c3027e6e8865a4c.zip | |
Implement [T]::align_to
Diffstat (limited to 'src/libcore/tests')
| -rw-r--r-- | src/libcore/tests/lib.rs | 2 | ||||
| -rw-r--r-- | src/libcore/tests/ptr.rs | 89 | ||||
| -rw-r--r-- | src/libcore/tests/slice.rs | 34 |
3 files changed, 125 insertions, 0 deletions
diff --git a/src/libcore/tests/lib.rs b/src/libcore/tests/lib.rs index 8c481338945..dbd26b2c718 100644 --- a/src/libcore/tests/lib.rs +++ b/src/libcore/tests/lib.rs @@ -41,6 +41,8 @@ #![feature(try_from)] #![feature(try_trait)] #![feature(exact_chunks)] +#![feature(slice_align_to)] +#![feature(align_offset)] #![feature(reverse_bits)] #![feature(inclusive_range_methods)] #![feature(iterator_find_map)] diff --git a/src/libcore/tests/ptr.rs b/src/libcore/tests/ptr.rs index 00f87336f3c..9384cb32798 100644 --- a/src/libcore/tests/ptr.rs +++ b/src/libcore/tests/ptr.rs @@ -296,3 +296,92 @@ fn write_unaligned_drop() { } DROPS.with(|d| assert_eq!(*d.borrow(), [0])); } + +#[test] +fn align_offset_zst() { + // For pointers of stride = 0, the pointer is already aligned or it cannot be aligned at + // all, because no amount of elements will align the pointer. + let mut p = 1; + while p < 1024 { + assert_eq!((p as *const ()).align_offset(p), 0); + if p != 1 { + assert_eq!(((p + 1) as *const ()).align_offset(p), !0); + } + p = (p + 1).next_power_of_two(); + } +} + +#[test] +fn align_offset_stride1() { + // For pointers of stride = 1, the pointer can always be aligned. The offset is equal to + // number of bytes. + let mut align = 1; + while align < 1024 { + for ptr in 1..2*align { + let expected = ptr % align; + let offset = if expected == 0 { 0 } else { align - expected }; + assert_eq!((ptr as *const u8).align_offset(align), offset, + "ptr = {}, align = {}, size = 1", ptr, align); + align = (align + 1).next_power_of_two(); + } + } +} + +#[test] +fn align_offset_weird_strides() { + #[repr(packed)] + struct A3(u16, u8); + struct A4(u32); + #[repr(packed)] + struct A5(u32, u8); + #[repr(packed)] + struct A6(u32, u16); + #[repr(packed)] + struct A7(u32, u16, u8); + #[repr(packed)] + struct A8(u32, u32); + #[repr(packed)] + struct A9(u32, u32, u8); + #[repr(packed)] + struct A10(u32, u32, u16); + + unsafe fn test_weird_stride<T>(ptr: *const T, align: usize) -> bool { + let numptr = ptr as usize; + let mut expected = usize::max_value(); + // Naive but definitely correct way to find the *first* aligned element of stride::<T>. + for el in 0..align { + if (numptr + el * ::std::mem::size_of::<T>()) % align == 0 { + expected = el; + break; + } + } + let got = ptr.align_offset(align); + if got != expected { + eprintln!("aligning {:p} (with stride of {}) to {}, expected {}, got {}", ptr, + ::std::mem::size_of::<T>(), align, expected, got); + return true; + } + return false; + } + + // For pointers of stride != 1, we verify the algorithm against the naivest possible + // implementation + let mut align = 1; + let mut x = false; + while align < 1024 { + for ptr in 1usize..4*align { + unsafe { + x |= test_weird_stride::<A3>(ptr as *const A3, align); + x |= test_weird_stride::<A4>(ptr as *const A4, align); + x |= test_weird_stride::<A5>(ptr as *const A5, align); + x |= test_weird_stride::<A6>(ptr as *const A6, align); + x |= test_weird_stride::<A7>(ptr as *const A7, align); + x |= test_weird_stride::<A8>(ptr as *const A8, align); + x |= test_weird_stride::<A9>(ptr as *const A9, align); + x |= test_weird_stride::<A10>(ptr as *const A10, align); + } + } + align = (align + 1).next_power_of_two(); + } + assert!(!x); +} diff --git a/src/libcore/tests/slice.rs b/src/libcore/tests/slice.rs index 19b5c86c474..8acb531b989 100644 --- a/src/libcore/tests/slice.rs +++ b/src/libcore/tests/slice.rs @@ -812,3 +812,37 @@ pub mod memchr { } } } + +#[test] +fn test_align_to_simple() { + let bytes = [1u8, 2, 3, 4, 5, 6, 7]; + let (prefix, aligned, suffix) = unsafe { bytes.align_to::<u16>() }; + assert_eq!(aligned.len(), 3); + assert!(prefix == [1] || suffix == [7]); + let expect1 = [1 << 8 | 2, 3 << 8 | 4, 5 << 8 | 6]; + let expect2 = [1 | 2 << 8, 3 | 4 << 8, 5 | 6 << 8]; + let expect3 = [2 | 3 << 8, 4 | 5 << 8, 6 | 7 << 8]; + let expect4 = [2 | 3 << 8, 4 | 5 << 8, 6 | 7 << 8]; + assert!(aligned == expect1 || aligned == expect2 || aligned == expect3 || aligned == expect4, + "aligned={:?} expected={:?} || {:?} || {:?} || {:?}", + aligned, expect1, expect2, expect3, expect4); +} + +#[test] +fn test_align_to_zst() { + let bytes = [1, 2, 3, 4, 5, 6, 7]; + let (prefix, aligned, suffix) = unsafe { bytes.align_to::<()>() }; + assert_eq!(aligned.len(), 0); + assert!(prefix == [1, 2, 3, 4, 5, 6, 7] || suffix == [1, 2, 3, 4, 5, 6, 7]); +} + +#[test] +fn test_align_to_non_trivial() { + #[repr(align(8))] struct U64(u64, u64); + #[repr(align(8))] struct U64U64U32(u64, u64, u32); + let data = [U64(1, 2), U64(3, 4), U64(5, 6), U64(7, 8), U64(9, 10), U64(11, 12), U64(13, 14), + U64(15, 16)]; + let (prefix, aligned, suffix) = unsafe { data.align_to::<U64U64U32>() }; + assert_eq!(aligned.len(), 4); + assert_eq!(prefix.len() + suffix.len(), 2); +} |
