#![cfg(any(cargo_difftests, docsrs))]
use std::ffi::{OsStr, OsString};
use std::path::{Path, PathBuf};
use cargo_difftests_core::CoreTestDesc;
#[cfg(cargo_difftests)]
extern "C" {
pub static __llvm_profile_runtime: i32;
fn __llvm_profile_set_filename(filename: *const libc::c_char);
fn __llvm_profile_write_file() -> libc::c_int;
fn __llvm_profile_reset_counters();
}
#[cfg(all(not(cargo_difftests), docsrs))]
unsafe fn __llvm_profile_set_filename(_: *const libc::c_char) {}
#[cfg(all(not(cargo_difftests), docsrs))]
unsafe fn __llvm_profile_write_file() -> libc::c_int {
0
}
#[cfg(all(not(cargo_difftests), docsrs))]
unsafe fn __llvm_profile_reset_counters() {}
pub struct TestDesc<T: serde::Serialize> {
pub bin_path: PathBuf,
pub extra: T,
}
pub struct DifftestsEnv {
llvm_profile_file_name: OsString,
llvm_profile_file_value: OsString,
llvm_profile_self_file: PathBuf,
}
impl DifftestsEnv {
pub fn env_for_children(&self) -> impl Iterator<Item = (&OsStr, &OsStr)> {
std::iter::once((
self.llvm_profile_file_name.as_os_str(),
self.llvm_profile_file_value.as_os_str(),
))
}
}
impl Drop for DifftestsEnv {
fn drop(&mut self) {
unsafe {
#[allow(temporary_cstring_as_ptr)]
__llvm_profile_set_filename(std::ffi::CString::new(self.llvm_profile_self_file.to_str().unwrap()).unwrap().as_ptr());
let r = __llvm_profile_write_file();
assert_eq!(r, 0);
}
}
}
pub fn init<T: serde::Serialize>(
desc: TestDesc<T>,
tmpdir: &Path,
) -> std::io::Result<DifftestsEnv> {
if tmpdir.exists() {
std::fs::remove_dir_all(tmpdir)?;
}
std::fs::create_dir_all(tmpdir)?;
let self_profile_file =
tmpdir.join(cargo_difftests_core::CARGO_DIFFTESTS_SELF_PROFILE_FILENAME);
std::fs::write(&self_profile_file, "")?;
let self_info_path = tmpdir.join(cargo_difftests_core::CARGO_DIFFTESTS_SELF_JSON_FILENAME);
let core_test_desc = CoreTestDesc {
bin_path: desc.bin_path,
extra: serde_json::to_value(&desc.extra).unwrap(),
};
let self_info = serde_json::to_string(&core_test_desc).unwrap();
std::fs::write(self_info_path, self_info)?;
std::fs::write(
tmpdir.join(cargo_difftests_core::CARGO_DIFFTESTS_VERSION_FILENAME),
env!("CARGO_PKG_VERSION"),
)?;
let profraw_path =
tmpdir.join(cargo_difftests_core::CARGO_DIFFTESTS_OTHER_PROFILE_FILENAME_TEMPLATE);
let r = Ok(DifftestsEnv {
llvm_profile_file_name: "LLVM_PROFILE_FILE".into(),
llvm_profile_file_value: profraw_path.into(),
llvm_profile_self_file: self_profile_file,
});
unsafe {
__llvm_profile_reset_counters();
}
r
}