Skip to content

Commit de33f9a

Browse files
author
Lukas Markeffsky
committed
add coretests for const align_offset
1 parent d4e692d commit de33f9a

File tree

2 files changed

+166
-0
lines changed

2 files changed

+166
-0
lines changed

library/core/tests/lib.rs

+1
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@
44
#![feature(array_windows)]
55
#![feature(bigint_helper_methods)]
66
#![feature(cell_update)]
7+
#![feature(const_align_offset)]
78
#![feature(const_assume)]
89
#![feature(const_black_box)]
910
#![feature(const_bool_to_option)]

library/core/tests/ptr.rs

+165
Original file line numberDiff line numberDiff line change
@@ -358,6 +358,23 @@ fn align_offset_zst() {
358358
}
359359
}
360360

361+
#[test]
362+
#[cfg(not(bootstrap))]
363+
fn align_offset_zst_const() {
364+
const {
365+
// For pointers of stride = 0, the pointer is already aligned or it cannot be aligned at
366+
// all, because no amount of elements will align the pointer.
367+
let mut p = 1;
368+
while p < 1024 {
369+
assert!(ptr::invalid::<()>(p).align_offset(p) == 0);
370+
if p != 1 {
371+
assert!(ptr::invalid::<()>(p + 1).align_offset(p) == !0);
372+
}
373+
p = (p + 1).next_power_of_two();
374+
}
375+
}
376+
}
377+
361378
#[test]
362379
fn align_offset_stride_one() {
363380
// For pointers of stride = 1, the pointer can always be aligned. The offset is equal to
@@ -379,6 +396,26 @@ fn align_offset_stride_one() {
379396
}
380397
}
381398

399+
#[test]
400+
#[cfg(not(bootstrap))]
401+
fn align_offset_stride_one_const() {
402+
const {
403+
// For pointers of stride = 1, the pointer can always be aligned. The offset is equal to
404+
// number of bytes.
405+
let mut align = 1;
406+
while align < 1024 {
407+
let mut ptr = 1;
408+
while ptr < 2 * align {
409+
let expected = ptr % align;
410+
let offset = if expected == 0 { 0 } else { align - expected };
411+
assert!(ptr::invalid::<u8>(ptr).align_offset(align) == offset);
412+
ptr += 1;
413+
}
414+
align = (align + 1).next_power_of_two();
415+
}
416+
}
417+
}
418+
382419
#[test]
383420
fn align_offset_various_strides() {
384421
unsafe fn test_stride<T>(ptr: *const T, align: usize) -> bool {
@@ -455,6 +492,134 @@ fn align_offset_various_strides() {
455492
assert!(!x);
456493
}
457494

495+
#[test]
496+
#[cfg(not(bootstrap))]
497+
fn align_offset_various_strides_const() {
498+
const unsafe fn test_stride<T>(ptr: *const T, numptr: usize, align: usize) {
499+
let mut expected = usize::MAX;
500+
// Naive but definitely correct way to find the *first* aligned element of stride::<T>.
501+
let mut el = 0;
502+
while el < align {
503+
if (numptr + el * ::std::mem::size_of::<T>()) % align == 0 {
504+
expected = el;
505+
break;
506+
}
507+
el += 1;
508+
}
509+
let got = ptr.align_offset(align);
510+
assert!(got == expected);
511+
}
512+
513+
// For pointers of stride != 1, we verify the algorithm against the naivest possible
514+
// implementation
515+
let mut align = 1;
516+
let limit = 1024;
517+
while align < limit {
518+
for ptr in 1usize..4 * align {
519+
unsafe {
520+
#[repr(packed)]
521+
struct A3(u16, u8);
522+
test_stride::<A3>(ptr::invalid::<A3>(ptr), ptr, align);
523+
524+
struct A4(u32);
525+
test_stride::<A4>(ptr::invalid::<A4>(ptr), ptr, align);
526+
527+
#[repr(packed)]
528+
struct A5(u32, u8);
529+
test_stride::<A5>(ptr::invalid::<A5>(ptr), ptr, align);
530+
531+
#[repr(packed)]
532+
struct A6(u32, u16);
533+
test_stride::<A6>(ptr::invalid::<A6>(ptr), ptr, align);
534+
535+
#[repr(packed)]
536+
struct A7(u32, u16, u8);
537+
test_stride::<A7>(ptr::invalid::<A7>(ptr), ptr, align);
538+
539+
#[repr(packed)]
540+
struct A8(u32, u32);
541+
test_stride::<A8>(ptr::invalid::<A8>(ptr), ptr, align);
542+
543+
#[repr(packed)]
544+
struct A9(u32, u32, u8);
545+
test_stride::<A9>(ptr::invalid::<A9>(ptr), ptr, align);
546+
547+
#[repr(packed)]
548+
struct A10(u32, u32, u16);
549+
test_stride::<A10>(ptr::invalid::<A10>(ptr), ptr, align);
550+
551+
test_stride::<u32>(ptr::invalid::<u32>(ptr), ptr, align);
552+
test_stride::<u128>(ptr::invalid::<u128>(ptr), ptr, align);
553+
}
554+
}
555+
align = (align + 1).next_power_of_two();
556+
}
557+
}
558+
559+
#[test]
560+
#[cfg(not(bootstrap))]
561+
fn align_offset_with_provenance_const() {
562+
const {
563+
let data = 42;
564+
565+
let ptr: *const i32 = &data;
566+
assert!(ptr.align_offset(1) == 0);
567+
assert!(ptr.align_offset(2) == 0);
568+
assert!(ptr.align_offset(4) == 0);
569+
assert!(ptr.align_offset(8) == usize::MAX);
570+
assert!(ptr.wrapping_byte_add(1).align_offset(1) == 0);
571+
assert!(ptr.wrapping_byte_add(1).align_offset(2) == usize::MAX);
572+
assert!(ptr.wrapping_byte_add(2).align_offset(1) == 0);
573+
assert!(ptr.wrapping_byte_add(2).align_offset(2) == 0);
574+
assert!(ptr.wrapping_byte_add(2).align_offset(4) == usize::MAX);
575+
assert!(ptr.wrapping_byte_add(3).align_offset(1) == 0);
576+
assert!(ptr.wrapping_byte_add(3).align_offset(2) == usize::MAX);
577+
578+
assert!(ptr.wrapping_add(42).align_offset(4) == 0);
579+
assert!(ptr.wrapping_add(42).align_offset(8) == usize::MAX);
580+
581+
let ptr1: *const i8 = ptr.cast();
582+
assert!(ptr1.align_offset(1) == 0);
583+
assert!(ptr1.align_offset(2) == 0);
584+
assert!(ptr1.align_offset(4) == 0);
585+
assert!(ptr1.align_offset(8) == usize::MAX);
586+
assert!(ptr1.wrapping_byte_add(1).align_offset(1) == 0);
587+
assert!(ptr1.wrapping_byte_add(1).align_offset(2) == 1);
588+
assert!(ptr1.wrapping_byte_add(1).align_offset(4) == 3);
589+
assert!(ptr1.wrapping_byte_add(1).align_offset(8) == usize::MAX);
590+
assert!(ptr1.wrapping_byte_add(2).align_offset(1) == 0);
591+
assert!(ptr1.wrapping_byte_add(2).align_offset(2) == 0);
592+
assert!(ptr1.wrapping_byte_add(2).align_offset(4) == 2);
593+
assert!(ptr1.wrapping_byte_add(2).align_offset(8) == usize::MAX);
594+
assert!(ptr1.wrapping_byte_add(3).align_offset(1) == 0);
595+
assert!(ptr1.wrapping_byte_add(3).align_offset(2) == 1);
596+
assert!(ptr1.wrapping_byte_add(3).align_offset(4) == 1);
597+
assert!(ptr1.wrapping_byte_add(3).align_offset(8) == usize::MAX);
598+
599+
let ptr2: *const i16 = ptr.cast();
600+
assert!(ptr2.align_offset(1) == 0);
601+
assert!(ptr2.align_offset(2) == 0);
602+
assert!(ptr2.align_offset(4) == 0);
603+
assert!(ptr2.align_offset(8) == usize::MAX);
604+
assert!(ptr2.wrapping_byte_add(1).align_offset(1) == 0);
605+
assert!(ptr2.wrapping_byte_add(1).align_offset(2) == usize::MAX);
606+
assert!(ptr2.wrapping_byte_add(2).align_offset(1) == 0);
607+
assert!(ptr2.wrapping_byte_add(2).align_offset(2) == 0);
608+
assert!(ptr2.wrapping_byte_add(2).align_offset(4) == 1);
609+
assert!(ptr2.wrapping_byte_add(2).align_offset(8) == usize::MAX);
610+
assert!(ptr2.wrapping_byte_add(3).align_offset(1) == 0);
611+
assert!(ptr2.wrapping_byte_add(3).align_offset(2) == usize::MAX);
612+
613+
let ptr3: *const i64 = ptr.cast();
614+
assert!(ptr3.align_offset(1) == 0);
615+
assert!(ptr3.align_offset(2) == 0);
616+
assert!(ptr3.align_offset(4) == 0);
617+
assert!(ptr3.align_offset(8) == usize::MAX);
618+
assert!(ptr3.wrapping_byte_add(1).align_offset(1) == 0);
619+
assert!(ptr3.wrapping_byte_add(1).align_offset(2) == usize::MAX);
620+
}
621+
}
622+
458623
#[test]
459624
fn offset_from() {
460625
let mut a = [0; 5];

0 commit comments

Comments
 (0)