test_fuzz_internal/
dirs.rs1use 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 target_directory(false).join(path_segment("impl_generic_args"))
64}
65
66#[must_use]
67fn generic_args_directory() -> PathBuf {
68 target_directory(false).join(path_segment("generic_args"))
69}
70
71#[must_use]
72fn corpus_directory() -> PathBuf {
73 target_directory(false).join(path_segment("corpus"))
74}
75
76#[must_use]
77fn output_directory() -> PathBuf {
78 target_directory(true).join(path_segment("output"))
79}
80
81#[must_use]
82pub fn path_segment(s: &str) -> String {
83 let maybe_id = maybe_id();
84 format!(
85 "{s}{}{}",
86 if maybe_id.is_some() { "_" } else { "" },
87 maybe_id.unwrap_or_default()
88 )
89}
90
91fn maybe_id() -> Option<String> {
92 env::var("TEST_FUZZ_ID").ok().or_else(|| {
93 if IN_TEST.load(Ordering::SeqCst) {
94 Some(thread_id())
95 } else {
96 None
97 }
98 })
99}
100
101fn thread_id() -> String {
102 format!("{:?}", std::thread::current().id()).replace(['(', ')'], "_")
103}
104
105#[must_use]
106pub fn target_directory(instrumented: bool) -> PathBuf {
107 let mut command = MetadataCommand::new();
108 if let Ok(path) = env::var("TEST_FUZZ_MANIFEST_PATH") {
109 command.manifest_path(path);
110 }
111 let mut target_dir = command.no_deps().exec().unwrap().target_directory;
112 if instrumented {
113 target_dir = target_dir.join("afl");
114 }
115 target_dir.into()
116}
117
118#[must_use]
119fn path_from_args_type<T>() -> String {
120 let type_name = type_name::<T>();
121 let n = type_name
122 .find("_fuzz__")
123 .unwrap_or_else(|| panic!("unexpected type name: `{type_name}`"));
124 type_name[..n].to_owned()
125}
126
127#[must_use]
128fn path_from_target(krate: &str, target: &str) -> String {
129 krate.replace('-', "_") + "::" + target
130}