Skip to main content

test_fuzz_internal/
dirs.rs

1use cargo_metadata::MetadataCommand;
2use std::{
3    any::type_name,
4    env,
5    path::PathBuf,
6    sync::atomic::{AtomicBool, Ordering},
7};
8
9pub static IN_TEST: AtomicBool = AtomicBool::new(false);
10
11#[must_use]
12pub fn impl_generic_args_directory_from_args_type<T>() -> PathBuf {
13    impl_generic_args_directory().join(path_from_args_type::<T>())
14}
15
16#[must_use]
17pub fn impl_generic_args_directory_from_target(krate: &str, target: &str) -> PathBuf {
18    impl_generic_args_directory().join(path_from_target(krate, target))
19}
20
21#[must_use]
22pub fn generic_args_directory_from_args_type<T>() -> PathBuf {
23    generic_args_directory().join(path_from_args_type::<T>())
24}
25
26#[must_use]
27pub fn generic_args_directory_from_target(krate: &str, target: &str) -> PathBuf {
28    generic_args_directory().join(path_from_target(krate, target))
29}
30
31#[must_use]
32pub fn corpus_directory_from_args_type<T>() -> PathBuf {
33    corpus_directory().join(path_from_args_type::<T>())
34}
35
36#[must_use]
37pub fn corpus_directory_from_target(krate: &str, target: &str) -> PathBuf {
38    corpus_directory().join(path_from_target(krate, target))
39}
40
41#[must_use]
42pub fn crashes_directory_from_target(krate: &str, target: &str) -> PathBuf {
43    output_directory_from_target(krate, target).join("default/crashes")
44}
45
46#[must_use]
47pub fn hangs_directory_from_target(krate: &str, target: &str) -> PathBuf {
48    output_directory_from_target(krate, target).join("default/hangs")
49}
50
51#[must_use]
52pub fn queue_directory_from_target(krate: &str, target: &str) -> PathBuf {
53    output_directory_from_target(krate, target).join("default/queue")
54}
55
56#[must_use]
57pub fn output_directory_from_target(krate: &str, target: &str) -> PathBuf {
58    output_directory().join(path_from_target(krate, target))
59}
60
61#[must_use]
62fn impl_generic_args_directory() -> PathBuf {
63    #[allow(clippy::disallowed_methods)]
64    target_directory(false, false).join(path_segment("impl_generic_args"))
65}
66
67#[must_use]
68fn generic_args_directory() -> PathBuf {
69    #[allow(clippy::disallowed_methods)]
70    target_directory(false, false).join(path_segment("generic_args"))
71}
72
73#[must_use]
74fn corpus_directory() -> PathBuf {
75    #[allow(clippy::disallowed_methods)]
76    target_directory(false, false).join(path_segment("corpus"))
77}
78
79#[must_use]
80fn output_directory() -> PathBuf {
81    #[allow(clippy::disallowed_methods)]
82    target_directory(false, true).join(path_segment("output"))
83}
84
85#[must_use]
86pub fn path_segment(s: &str) -> String {
87    let maybe_id = maybe_id();
88    format!(
89        "{s}{}{}",
90        if maybe_id.is_some() { "_" } else { "" },
91        maybe_id.unwrap_or_default()
92    )
93}
94
95fn maybe_id() -> Option<String> {
96    env::var("TEST_FUZZ_ID").ok().or_else(|| {
97        if IN_TEST.load(Ordering::SeqCst) {
98            Some(thread_id())
99        } else {
100            None
101        }
102    })
103}
104
105fn thread_id() -> String {
106    format!("{:?}", std::thread::current().id()).replace(['(', ')'], "_")
107}
108
109#[must_use]
110pub fn target_directory(coverage: bool, fuzzing: bool) -> PathBuf {
111    assert!(!(coverage && fuzzing));
112    let mut command = MetadataCommand::new();
113    if let Ok(path) = env::var("TEST_FUZZ_MANIFEST_PATH") {
114        command.manifest_path(path);
115    }
116    let mut target_dir = command.no_deps().exec().unwrap().target_directory;
117    if coverage {
118        target_dir = target_dir.join("coverage");
119    }
120    if fuzzing {
121        target_dir = target_dir.join("afl");
122    }
123    target_dir.into()
124}
125
126#[must_use]
127fn path_from_args_type<T>() -> String {
128    let type_name = type_name::<T>();
129    let n = type_name
130        .find("_fuzz__")
131        .unwrap_or_else(|| panic!("unexpected type name: `{type_name}`"));
132    type_name[..n].to_owned()
133}
134
135#[must_use]
136fn path_from_target(krate: &str, target: &str) -> String {
137    krate.replace('-', "_") + "::" + target
138}