use devutils::*;
use std::alloc::Layout;
use std::alloc::GlobalAlloc;
use devutils::nextest_integration_tests;
use devutils::get_devsmalloc;
use smmalloc::plat;
fn assert_all_bytes_val(ptr: *mut u8, numbytes: usize, val: u8, skipfirst: usize) {
unsafe {
let slice = std::slice::from_raw_parts(ptr, numbytes);
for (i, &byte) in slice.iter().enumerate() {
if i >= skipfirst {
assert_eq!(byte, val, "Byte at offset {} is 0x{:02x}, expected {}", i, byte, val);
}
}
}
}
nextest_integration_tests! {
fn zeromem_first_time() {
let sm = get_devsmalloc!();
let numbytes = 1 << (plat::p::SC_FOR_PAGE + 1);
let l = Layout::from_size_align(numbytes, 1).unwrap();
let p = unsafe { sm.alloc_zeroed(l) };
assert_all_bytes_val(p, numbytes, 0, 0);
}
fn zeromem_second_time() {
let sm = get_devsmalloc!();
let numbytes = 1 << (plat::p::SC_FOR_PAGE + 1);
let l = Layout::from_size_align(numbytes, 1).unwrap();
let p1 = unsafe { sm.alloc_zeroed(l) };
unsafe { core::ptr::write_bytes(p1, 1, numbytes) };
let p2 = unsafe { sm.alloc_zeroed(l) };
unsafe { core::ptr::write_bytes(p1, 2, numbytes) };
unsafe { sm.dealloc(p2, l) };
unsafe { sm.dealloc(p1, l) };
let p3 = unsafe { sm.alloc_zeroed(l) };
if p3 != p1 {
panic!("cannot re-allocate memory previously used - test cannot run");
}
assert_all_bytes_val(p3, numbytes, 0, 0);
}
fn dont_zeromem() {
let sm = get_devsmalloc!();
let numbytes = 1 << (plat::p::SC_FOR_PAGE + 1);
let l = Layout::from_size_align(1 << (plat::p::SC_FOR_PAGE+1), 1).unwrap();
let p1 = unsafe { sm.alloc(l) };
unsafe { core::ptr::write_bytes(p1, 1, numbytes) };
unsafe { sm.dealloc(p1, l) };
let p2 = unsafe { sm.alloc(l) };
if p1 != p2 {
panic!("cannot re-allocate memory previously used - test cannot run");
}
assert_all_bytes_val(p2, numbytes, 1, 4);
}
fn pop_push_pop_pop() {
let sm = get_devsmalloc!();
let l = Layout::from_size_align(65536, 1).unwrap();
let p = unsafe { sm.alloc(l) };
unsafe { sm.dealloc(p, l) };
unsafe { sm.alloc(l) };
unsafe { sm.alloc(l) };
}
fn large_realloc_down_realloc_back_up() {
const LARGE_SLOT_SIZE: usize = 2usize.pow(24);
let l1 = Layout::from_size_align(LARGE_SLOT_SIZE * 2, 1).unwrap();
let l2 = Layout::from_size_align(LARGE_SLOT_SIZE, 1).unwrap();
let p1 = unsafe { get_devsmalloc!().alloc(l1) };
assert!(!p1.is_null());
let p2 = unsafe { get_devsmalloc!().realloc(p1, l1, LARGE_SLOT_SIZE) };
assert!(!p2.is_null());
let p3 = unsafe { get_devsmalloc!().realloc(p2, l2, LARGE_SLOT_SIZE * 2) };
assert!(!p3.is_null());
}
fn test_alloc_1_byte_then_dealloc() {
let layout = Layout::from_size_align(1, 1).unwrap();
let p = unsafe { get_devsmalloc!().alloc(layout) };
assert!(!p.is_null());
unsafe { get_devsmalloc!().dealloc(p, layout) };
}
fn threads_1_alloc_x() {
help_test_multithreaded(1, 100, false, false, false);
}
fn threads_1_alloc_dealloc_x() {
help_test_multithreaded(1, 100, true, false, false);
}
fn threads_1_alloc_dealloc_realloc_x() {
help_test_multithreaded(1, 100, true, true, false);
}
fn threads_1_alloc_dealloc_with_writes_x() {
help_test_multithreaded(1, 100, true, false, true);
}
fn threads_1_alloc_dealloc_realloc_with_writes_x() {
help_test_multithreaded(1, 100, true, true, true);
}
fn threads_2_alloc_x() {
help_test_multithreaded(2, 100, false, false, false);
}
fn threads_2_alloc_dealloc_x() {
help_test_multithreaded(2, 100, true, false, false);
}
fn threads_2_alloc_dealloc_realloc_x() {
help_test_multithreaded(2, 100, true, true, false);
}
fn threads_2_alloc_dealloc_with_writes_x() {
help_test_multithreaded(2, 100, true, false, true);
}
fn threads_2_alloc_dealloc_realloc_with_writes_x() {
help_test_multithreaded(2, 100, true, true, true);
}
fn threads_4096_alloc_x() {
help_test_multithreaded(4096, 100, false, false, false);
}
fn threads_4096_alloc_dealloc_x() {
help_test_multithreaded(4096, 100, true, false, false);
}
fn threads_4096_alloc_dealloc_realloc_x() {
help_test_multithreaded(4096, 100, true, true, false);
}
fn threads_4096_alloc_dealloc_with_writes_x() {
help_test_multithreaded(4096, 100, true, false, true);
}
fn threads_4096_alloc_dealloc_realloc_with_writes_x() {
help_test_multithreaded(4096, 100, true, true, true);
}
}
fn help_test_multithreaded(threads: u32, iters: u64, dealloc: bool, realloc: bool, writes: bool) {
let f = match (dealloc, realloc, writes) {
(true, true, true) => { adrww }
(true, true, false) => { adr }
(true, false, true) => { adww }
(true, false, false) => { ad }
(false, false, true) => { aww }
(false, false, false) => { a }
(false, _, _) => panic!()
};
let mut tses: Vec<TestState> = Vec::with_capacity(threads as usize);
for _i in 0..threads {
tses.push(TestState::new(iters, 0));
}
help_test_multithreaded_with_allocator(f, threads, iters, get_devsmalloc!(), &mut tses);
}
#[test]
fn aaa_require_nextest() {
if std::env::var("NEXTEST").is_ok() {
return;
}
panic!(
"\n\n\
\x1b[1;31merror:\x1b[0m This project requires cargo-nextest for testing.\n\n\
\x20 Run tests with: \x1b[1;32mcargo nextest run\x1b[0m\n\
\x20 Install with: cargo install cargo-nextest\n"
);
}