#[cfg(not(any(test, rustdoc)))]
use alloc::prelude::v1::*;
#[cfg(any(test, rustdoc))]
use std::prelude::v1::*;
use super::{Allocator, Region};
use alloc::alloc::Layout;
use core::mem::size_of;
#[test]
fn add_region_single() {
const HEAP_SIZE: usize = 1024;
let heap = Box::into_raw(Box::new([0u8; HEAP_SIZE])) as *mut u8;
let mut allocator = Allocator::empty();
unsafe {
allocator.add_region(heap as usize, HEAP_SIZE);
let region = allocator.get_region_first().unwrap();
assert_eq!(
region.data_ptr().unwrap().as_ptr(),
heap.offset(size_of::<Region>() as isize)
);
}
core::mem::drop(allocator);
core::mem::drop(unsafe { Box::from_raw(heap) });
}
#[test]
fn add_region_multiple() {
const HEAP_SIZE: usize = 1024;
let heap_one = Box::into_raw(Box::new([0u8; HEAP_SIZE])) as *mut u8;
let heap_two = Box::into_raw(Box::new([0u8; HEAP_SIZE])) as *mut u8;
let mut allocator = Allocator::empty();
unsafe {
allocator.add_region(heap_one as usize, HEAP_SIZE);
allocator.add_region(heap_two as usize, HEAP_SIZE);
let region_one = allocator.get_region_first().unwrap();
assert_eq!(
region_one.data_ptr().unwrap().as_ptr(),
heap_one.offset(size_of::<Region>() as isize)
);
let region_two = allocator.get_region_for_ptr(region_one.next as *mut u8).unwrap();
assert_eq!(
region_two.data_ptr().unwrap().as_ptr(),
heap_two.offset(size_of::<Region>() as isize)
);
}
}
#[test]
fn allocation_single() {
const HEAP_SIZE: usize = 1024;
let heap = Box::into_raw(Box::new([0u8; HEAP_SIZE])) as *mut u8;
let mut allocator = Allocator::empty();
unsafe {
allocator.add_region(heap as usize, HEAP_SIZE);
}
let layout = Layout::from_size_align(size_of::<usize>() * 4, 1).unwrap();
allocator.allocate(layout).expect("failed to allocate");
let region = allocator.get_region_first().expect("failed to get region");
assert_eq!(region.get_used(), true);
assert_eq!(region.size(), size_of::<usize>() * 4);
let next = allocator.get_region_for_ptr(region.next as *mut u8)
.expect("failed to get next region");
assert_eq!(next.get_used(), false);
}
#[test]
fn allocation_and_deallocation_multiple() {
const HEAP_SIZE: usize = 4096;
let heap = Box::into_raw(Box::new([0u8; HEAP_SIZE])) as *mut u8;
let mut allocator = Allocator::empty();
unsafe {
allocator.add_region(heap as usize, HEAP_SIZE);
}
for _ in 0..100 {
let layout = Layout::from_size_align(size_of::<usize>() * 4, 1).unwrap();
let ptr = allocator.allocate(layout).expect("failed to allocate");
allocator.deallocate(ptr, layout);
}
}
#[test]
fn allocation_and_deallocation_single() {
const HEAP_SIZE: usize = 1024;
let heap = Box::into_raw(Box::new([0u8; HEAP_SIZE])) as *mut u8;
let mut allocator = Allocator::empty();
unsafe {
allocator.add_region(heap as usize, HEAP_SIZE);
}
let layout = Layout::from_size_align(size_of::<usize>() * 4, 1).unwrap();
let ptr = allocator.allocate(layout).expect("failed to allocate");
let region = allocator.get_region_first().expect("failed to get region");
assert_eq!(region.get_used(), true);
assert_eq!(region.size(), size_of::<usize>() * 4);
core::mem::drop(region);
allocator.deallocate(ptr, layout);
let region = allocator.get_region_first().expect("failed to get region");
assert_eq!(region.get_used(), false);
}
#[test]
fn allocation_and_deallocation_combines_forward() {
const HEAP_SIZE: usize = 1024;
let heap = Box::into_raw(Box::new([0u8; HEAP_SIZE])) as *mut u8;
let mut allocator = Allocator::empty();
unsafe {
allocator.add_region(heap as usize, HEAP_SIZE);
}
let region = allocator.get_region_first().expect("failed to get region");
let region_size = region.size();
core::mem::drop(region);
let layout = Layout::from_size_align(size_of::<usize>() * 4, 1).unwrap();
let ptr = allocator.allocate(layout).expect("failed to allocate");
let region = allocator.get_region_first().expect("failed to get region");
assert_eq!(region.get_used(), true);
assert_eq!(region.size(), size_of::<usize>() * 4);
let next_region = allocator.get_region_for_ptr(region.next as *mut u8).unwrap();
assert_eq!(next_region.get_used(), false);
core::mem::drop(next_region);
core::mem::drop(region);
allocator.deallocate(ptr, layout);
let region = allocator.get_region_first().expect("failed to get region");
assert_eq!(region.size(), region_size);
assert_eq!(region.get_used(), false);
}
#[test]
fn allocation_and_deallocation_combines_forward_recursively() {
const HEAP_SIZE: usize = 1024;
let heap = Box::into_raw(Box::new([0u8; HEAP_SIZE])) as *mut u8;
let mut allocator = Allocator::empty();
unsafe {
allocator.add_region(heap as usize, HEAP_SIZE);
}
let region = allocator.get_region_first().expect("failed to get region");
let region_size = region.size();
core::mem::drop(region);
let layout = Layout::from_size_align(size_of::<usize>() * 4, 1).unwrap();
let ptr = allocator.allocate(layout).expect("failed to allocate");
{
let fptr = allocator.allocate(layout).expect("failed to allocate");
let region = allocator
.get_region_for_data_ptr(fptr.as_ptr())
.expect("failed to get region");
region.set_used(false);
}
allocator.deallocate(ptr, layout);
let region = allocator.get_region_first().expect("failed to get region");
assert_eq!(region.size(), region_size);
assert_eq!(region.get_used(), false);
}
#[test]
fn allocation_and_deallocation_combines_backwards() {
const HEAP_SIZE: usize = 1024;
let heap = Box::into_raw(Box::new([0u8; HEAP_SIZE])) as *mut u8;
let mut allocator = Allocator::empty();
unsafe {
allocator.add_region(heap as usize, HEAP_SIZE);
}
let region = allocator.get_region_first().expect("failed to get region");
let region_size = region.size();
core::mem::drop(region);
let layout = Layout::from_size_align(size_of::<usize>() * 4, 1).unwrap();
let ptr_one = allocator.allocate(layout).expect("failed to allocate");
let ptr_two = allocator.allocate(layout).expect("failed to allocate");
allocator.deallocate(ptr_one, layout);
allocator.deallocate(ptr_two, layout);
let region = allocator.get_region_first().expect("failed to get region");
assert_eq!(region.size(), region_size);
assert_eq!(region.get_used(), false);
}
#[test]
fn allocation_and_deallocation_combines_backwards_recursively() {
const HEAP_SIZE: usize = 1024;
let heap = Box::into_raw(Box::new([0u8; HEAP_SIZE])) as *mut u8;
let mut allocator = Allocator::empty();
unsafe {
allocator.add_region(heap as usize, HEAP_SIZE);
}
let region = allocator.get_region_first().expect("failed to get region");
let region_size = region.size();
core::mem::drop(region);
for _ in 0..3 {
let layout = Layout::from_size_align(size_of::<usize>() * 4, 1).unwrap();
let fptr = allocator.allocate(layout).expect("failed to allocate");
let region = allocator
.get_region_for_data_ptr(fptr.as_ptr())
.expect("failed to get region");
region.set_used(false);
}
let layout = Layout::from_size_align(size_of::<usize>() * 4, 1).unwrap();
let ptr = allocator.allocate(layout).expect("failed to allocate");
allocator.deallocate(ptr, layout);
let region = allocator.get_region_first().expect("failed to get region");
assert_eq!(region.size(), region_size);
assert_eq!(region.get_used(), false);
}