use std::alloc::Allocator as AllocatorTrait;
use super::*;
use const_str;
use indoc;
use std::process::Command;
use std::vec::Vec;
use test_binary::build_test_binary;
use std::alloc::Layout;
#[test]
fn page_boundary() {
let _ = std::fs::remove_file("test_page_boundary.odb");
let _ = std::fs::remove_file("test_page_boundary.log");
type V = Vec<u64, Allocator>;
let mut h = unsafe {
Holder::<V>::open(
"test_page_boundary",
None,
MI,
0xfedcba9876543210,
|a| V::new_in(a),
)
}
.unwrap();
let mut w = h.write();
const I: usize = 16 * KI;
w.extend_from_slice(&[0u64; I]);
for i in 0..I * 8 - 7 {
let a = unsafe { w.as_mut_ptr().byte_add(i).as_mut() }.unwrap();
*a = !*a;
}
w.commit();
drop(w);
let r = h.read();
assert_eq!(
*r,
[vec![0x00ff00ff00ff00ff], vec![0u64; I - 2], vec![0xff00ff00ff00ff00]]
.concat()
);
drop(r);
drop(h);
let _ = std::fs::remove_file("test_page_boundary.odb");
let _ = std::fs::remove_file("test_page_boundary.log");
}
#[test]
fn read_recovery() {
let _ = std::fs::remove_file("test_read_recovery.odb");
let _ = std::fs::remove_file("test_read_recovery.log");
type V = Vec<i64, Allocator>;
#[cfg(target_pointer_width = "64")]
const ADDRESS: usize = 0x70ffe6f00000;
#[cfg(target_pointer_width = "32")]
const ADDRESS: usize = 0xb6f00000;
let mut h = unsafe {
Holder::<V>::open(
"test_read_recovery",
Some(ADDRESS),
MI,
0xfedcba9876543210,
|a| V::new_in(a.clone()),
)
}
.unwrap();
let mut w = h.write();
const VS: i64 = 120 * KI as i64;
let v: Vec<i64> = (0i64..VS).collect();
w.extend_from_slice(&v);
w.commit();
drop(w);
assert_eq!(*h.read(), v);
let test_bin_path = build_test_binary("suicider", "testbins")
.expect("error building test binary");
let output = Command::new(test_bin_path)
.output()
.expect("failed to execute test binary");
assert_eq!(
output.stdout,
const_str::to_byte_array!(const_str::format!("w: {}\n", 1 - VS))
);
assert_eq!(*h.read(), v);
drop(h);
let _ = std::fs::remove_file("test_read_recovery.odb");
let _ = std::fs::remove_file("test_read_recovery.log");
}
#[test]
fn grow_and_shrink() {
let _ = std::fs::remove_file("test_grow_and_shrink.odb");
let _ = std::fs::remove_file("test_grow_and_shrink.log");
type V = Vec<u8, Allocator>;
struct S {
onegin: V,
tworoads: V,
threelittlepigs: V,
fourseasons: V,
}
let mut h = unsafe {
Holder::<S>::open(
"test_grow_and_shrink",
None,
MI,
0xfedcba9876543210,
|a| S {
onegin: V::new_in(a.clone()),
tworoads: V::new_in(a.clone()),
threelittlepigs: V::new_in(a.clone()),
fourseasons: V::new_in(a.clone()),
},
)
}
.unwrap();
let mut w = h.write();
w.onegin.extend_from_slice(b"My uncle has most honest principles:\n"); let a1 = w.onegin.as_ptr();
let l1 = w.onegin.len();
w.tworoads.extend_from_slice(b"TWO roads diverged in a yellow wood\n"); let a2 = w.tworoads.as_ptr();
let l2 = w.tworoads.len();
w.tworoads.extend_from_slice(b"And sorry I could not travel");
assert_eq!(a2, w.tworoads.as_ptr());
w.tworoads.extend_from_slice(b" both\n"); assert_eq!(a2, w.tworoads.as_ptr());
w.onegin.extend_from_slice(b"when he was taken gravely ill,\n"); let a1m = w.onegin.as_ptr();
assert_ne!(a1, a1m);
w.commit();
w.tworoads.truncate(l2);
w.tworoads.shrink_to_fit();
w.threelittlepigs.extend_from_slice(b"Why don't you, sit right back\n"); w.threelittlepigs.extend_from_slice(b"And I, I may tell you, a tale\n"); let a3 = w.threelittlepigs.as_ptr();
assert_eq!(a3, a1);
w.onegin.truncate(l1);
w.onegin.shrink_to_fit();
w.fourseasons.extend_from_slice(b"All four seasons are special");
let a4 = w.fourseasons.as_ptr();
assert!(a2 < a4);
assert_eq!(unsafe { a2.byte_add(64) }, a4);
assert!(a4 < a1m);
assert_eq!(unsafe { a4.byte_add(ALLOCATION_QUANTUM) }, a1m);
w.threelittlepigs.extend_from_slice(indoc::indoc!(
b"
A tale of three, little pigs
And a big, bad, wolfff
"
));
let a3m = w.threelittlepigs.as_ptr();
assert_eq!(unsafe { a1m.byte_add(64) }, a3m);
drop(w);
drop(h);
let _ = std::fs::remove_file("test_grow_and_shrink.odb");
let _ = std::fs::remove_file("test_grow_and_shrink.log");
}
#[test]
#[should_panic]
fn allocator_leak_should_panic() {
let _ = std::fs::remove_file("allocator_leak.odb");
let _ = std::fs::remove_file("allocator_leak.log");
let mut h = unsafe {
Holder::<()>::open("allocator_leak",
None,
8*KI,
0xfedcba9876567890,
|_| (),
)
}
.unwrap();
let _ = std::fs::remove_file("allocator_leak.odb");
let _ = std::fs::remove_file("allocator_leak.log");
let w = h.write();
let a0 = w.allocator();
if let Ok(l) = Layout::from_size_align(2, 2) {
let _ = a0.allocate(l);
let a1 = a0.clone();
drop(w);
let _ = a1.allocate(l);
}
}