use std::path::PathBuf;
#[doc(hidden)]
#[macro_export]
macro_rules! __item_path__ {
() => {{
fn __bolero_item_path__() {}
fn __resolve_item_path__<T>(_: T) -> &'static str {
::core::any::type_name::<T>()
}
__resolve_item_path__(__bolero_item_path__)
}};
}
#[cfg(all(not(kani), test))]
mod tests;
#[doc(hidden)]
#[derive(Clone, Debug)]
pub struct TargetLocation {
pub package_name: &'static str,
pub manifest_dir: &'static str,
pub module_path: &'static str,
pub file: &'static str,
pub line: u32,
pub item_path: &'static str,
pub test_name: Option<String>,
}
#[cfg(kani)]
impl TargetLocation {
pub fn should_run(&self) -> bool {
true
}
pub fn abs_path(&self) -> Option<PathBuf> {
None
}
pub fn work_dir(&self) -> Option<PathBuf> {
None
}
pub fn is_harnessed(&self) -> bool {
false
}
}
#[cfg(not(kani))]
impl TargetLocation {
pub fn should_run(&self) -> bool {
if let Ok(mode) = ::std::env::var("CARGO_BOLERO_SELECT") {
match mode.as_str() {
"all" => self.print(),
"one" if self.is_exact_match() => self.print(),
_ => {}
}
return false;
}
true
}
fn is_exact_match(&self) -> bool {
let test_name = self.item_path();
std::env::args().take(2).any(|path| path == test_name)
}
fn print(&self) {
println!(
r#"
{{"__bolero_target":"v0.5.0","exe":{:?},"work_dir":{:?},"package_name":{:?},"is_harnessed":{:?},"test_name":{:?}}}"#,
::std::env::current_exe()
.expect("valid current_exe")
.display(),
self.work_dir().expect("valid work_dir").display(),
&self.package_name,
self.is_harnessed(),
self.item_path(),
);
}
pub fn abs_path(&self) -> Option<PathBuf> {
let file = std::path::Path::new(self.file);
#[cfg(not(miri))] {
if let Ok(file) = file.canonicalize() {
return Some(file);
}
}
std::path::Path::new(self.manifest_dir)
.ancestors()
.find_map(|ancestor| {
let path = ancestor.join(file);
if path.exists() {
Some(path)
} else {
None
}
})
}
pub fn work_dir(&self) -> Option<PathBuf> {
let mut work_dir = self.abs_path()?;
work_dir.pop();
if !self.is_harnessed() {
return Some(work_dir);
}
work_dir.push("__fuzz__");
if let Some(test_name) = self.test_name.as_ref() {
work_dir.push(test_name);
} else {
work_dir.push(self.fuzz_dir());
}
Some(work_dir)
}
pub fn is_harnessed(&self) -> bool {
if std::thread::current()
.name()
.filter(|name| name != &"main")
.is_some()
{
return true;
}
let mut parts: Vec<_> = self.item_path.split("::").collect();
while parts.pop().expect("empty path") != "__bolero_item_path__" {}
!matches!(
parts.last().cloned(),
Some("main") if parts.len() == 2
)
}
fn fuzz_dir(&self) -> String {
let test_name = self.item_path();
let mut components: Vec<_> = test_name.split("::").collect();
let last = components.len() - 1;
let name = &mut components[last];
if name.starts_with("test_") || name.starts_with("fuzz_") {
*name = &name[5..];
}
if name.ends_with("_test") || name.ends_with("_fuzz") {
let len = name.len();
*name = &name[..(len - 5)];
}
components.join("__")
}
pub fn item_path(&self) -> String {
Self::format_symbol_name(self.item_path)
}
fn format_symbol_name(name: &str) -> String {
let mut parts: Vec<_> = name.split("::").collect();
while parts.pop().expect("empty path") != "__bolero_item_path__" {}
match parts.last().cloned() {
Some("main") if parts.len() == 2 => {
parts.pop().expect("main symbol");
}
Some("{{closure}}") => {
parts.pop().expect("unused symbol");
}
_ => {}
}
if parts.len() == 1 {
parts.pop().unwrap().to_string()
} else {
parts[1..].join("::")
}
}
}