]> git.lizzy.rs Git - rust.git/blob - tests/run-pass/heap_allocator.rs
update miri-seed handling for run-pass test suite
[rust.git] / tests / run-pass / heap_allocator.rs
1 #![feature(allocator_api)]
2
3 use std::ptr::NonNull;
4 use std::alloc::{Global, Alloc, Layout, System};
5 use std::slice;
6
7 fn check_alloc<T: Alloc>(mut allocator: T) { unsafe {
8     for &align in &[4, 8, 16, 32] {
9         let layout = Layout::from_size_align(20, align).unwrap();
10
11         for _ in 0..32 {
12             let a = allocator.alloc(layout).unwrap();
13             assert_eq!(a.as_ptr() as usize % align, 0, "pointer is incorrectly aligned");
14             allocator.dealloc(a, layout);
15         }
16
17         let p1 = allocator.alloc_zeroed(layout).unwrap();
18         assert_eq!(p1.as_ptr() as usize % align, 0, "pointer is incorrectly aligned");
19
20         let p2 = allocator.realloc(p1, layout, 40).unwrap();
21         let layout = Layout::from_size_align(40, align).unwrap();
22         assert_eq!(p2.as_ptr() as usize % align, 0, "pointer is incorrectly aligned");
23         let slice = slice::from_raw_parts(p2.as_ptr(), 20);
24         assert_eq!(&slice, &[0_u8; 20]);
25
26         // old size == new size
27         let p3 = allocator.realloc(p2, layout, 40).unwrap();
28         assert_eq!(p3.as_ptr() as usize % align, 0, "pointer is incorrectly aligned");
29         let slice = slice::from_raw_parts(p3.as_ptr(), 20);
30         assert_eq!(&slice, &[0_u8; 20]);
31
32         // old size > new size
33         let p4 = allocator.realloc(p3, layout, 10).unwrap();
34         let layout = Layout::from_size_align(10, align).unwrap();
35         assert_eq!(p4.as_ptr() as usize % align, 0, "pointer is incorrectly aligned");
36         let slice = slice::from_raw_parts(p4.as_ptr(), 10);
37         assert_eq!(&slice, &[0_u8; 10]);
38
39         allocator.dealloc(p4, layout);
40     }
41 } }
42
43 fn check_align_requests<T: Alloc>(mut allocator: T) {
44     for &size in &[2, 8, 64] { // size less than and bigger than alignment
45         for &align in &[4, 8, 16, 32] { // Be sure to cover less than and bigger than `MIN_ALIGN` for all architectures
46             let iterations = 32;
47             unsafe {
48                 let pointers: Vec<_> = (0..iterations).map(|_| {
49                     allocator.alloc(Layout::from_size_align(size, align).unwrap()).unwrap()
50                 }).collect();
51                 for &ptr in &pointers {
52                     assert_eq!((ptr.as_ptr() as usize) % align, 0,
53                             "Got a pointer less aligned than requested")
54                 }
55
56                 // Clean up.
57                 for &ptr in &pointers {
58                     allocator.dealloc(ptr, Layout::from_size_align(size, align).unwrap())
59                 }
60             }
61         }
62     }
63 }
64
65 fn global_to_box() {
66     type T = [i32; 4];
67     let l = Layout::new::<T>();
68     // allocate manually with global allocator, then turn into Box and free there
69     unsafe {
70         let ptr = Global.alloc(l).unwrap().as_ptr() as *mut T;
71         let b = Box::from_raw(ptr);
72         drop(b);
73     }
74 }
75
76 fn box_to_global() {
77     type T = [i32; 4];
78     let l = Layout::new::<T>();
79     // allocate with the Box, then deallocate manually with global allocator
80     unsafe {
81         let b = Box::new(T::default());
82         let ptr = Box::into_raw(b);
83         Global.dealloc(NonNull::new(ptr as *mut u8).unwrap(), l);
84     }
85 }
86
87 fn main() {
88     check_alloc(System);
89     check_alloc(Global);
90     check_align_requests(System);
91     check_align_requests(Global);
92     global_to_box();
93     box_to_global();
94 }