use core::mem::{offset_of, size_of};
use std::io::{Cursor, Write};
use std::path::Path;
use proptest::prelude::*;
use super::{Cache, Entry, Header, ParsedHeader, MAGIC};
fn print_cache(cache: &Cache) {
eprintln!();
for e in cache.iter().unwrap() {
let e = e.unwrap();
eprintln!(
" {} => {}",
e.file_name.to_string_lossy(),
e.full_path.display()
);
}
}
#[test]
fn load() {
let cache = Cache::load("tests/ld.so-1.7.0/ld.so.cache").unwrap();
print_cache(&cache);
}
#[test]
fn load_compat() {
let cache = Cache::load("tests/ld.so-1.7.0/ld.so.cache.compat").unwrap();
print_cache(&cache);
}
#[test]
fn parse_empty() {
ParsedHeader::parse(Path::new("empty"), &[]).unwrap_err();
}
prop_compose! {
fn header_components()
(size in proptest::num::u16::ANY)
(
lib_count in 0_u32..=(u32::from(size) / size_of::<Entry>() as u32),
bytes in prop::collection::vec(0_u8.., 0..=(2 * usize::from(size))),
)
-> (u32, Vec<u8>)
{
(lib_count, bytes)
}
}
proptest! {
#[test]
fn load_random(
(lib_count, bytes) in header_components(),
random_u8 in proptest::num::u8::ANY,
random_u32 in proptest::num::u32::ANY,
) {
load_random0([random_u8], lib_count, &bytes)?;
load_random0([random_u8], random_u32, &bytes)?;
}
}
fn load_random0(padding: [u8; 1], lib_count: u32, bytes: &[u8]) -> Result<(), TestCaseError> {
let mut cursor = Cursor::new(Vec::<u8>::with_capacity(size_of::<Header>() + bytes.len()));
cursor.write_all(MAGIC)?;
cursor.write_all(&padding)?;
cursor.write_all(&lib_count.to_ne_bytes())?;
cursor.write_all(bytes)?;
let bytes = cursor.into_inner();
let Ok(p_header) = ParsedHeader::parse(Path::new("random"), &bytes) else {
return Ok(());
};
let p_lib_count = u32::try_from(p_header.lib_count).unwrap();
let lib_count_bytes = bytes
.get(offset_of!(Header, lib_count)..(offset_of!(Header, lib_count) + 4))
.unwrap_or(&[]);
prop_assert_eq!(lib_count_bytes, p_lib_count.to_ne_bytes());
Ok(())
}