trident_client/
utils.rs

1use crate::test_generator::Error;
2
3use crate::constants::*;
4use fehler::{throw, throws};
5use std::path::Path;
6use std::path::PathBuf;
7use tokio::fs;
8
9#[macro_export]
10macro_rules! construct_path {
11    ($root:expr, $($component:expr),*) => {
12        {
13            let mut path = $root.to_owned();
14            $(path = path.join($component);)*
15            path
16        }
17    };
18}
19#[macro_export]
20macro_rules! load_template {
21    ($file:expr) => {
22        include_str!(concat!(env!("CARGO_MANIFEST_DIR"), $file))
23    };
24}
25
26#[throws]
27pub async fn create_directory_all(path: &PathBuf) {
28    match path.exists() {
29        true => {}
30        false => {
31            fs::create_dir_all(path).await?;
32        }
33    };
34}
35
36#[throws]
37pub async fn create_file(root: &PathBuf, path: &PathBuf, content: &str) {
38    let file = path.strip_prefix(root)?.to_str().unwrap_or_default();
39
40    match path.exists() {
41        true => {
42            println!("{SKIP} [{file}] already exists")
43        }
44        false => {
45            fs::write(path, content).await?;
46            println!("{FINISH} [{file}] created");
47        }
48    };
49}
50
51#[throws]
52pub fn get_fuzz_id(fuzz_dir_path: &Path) -> i32 {
53    if fuzz_dir_path.exists() {
54        if fuzz_dir_path.read_dir()?.next().is_none() {
55            0
56        } else {
57            let entries = fuzz_dir_path.read_dir()?;
58            let mut max_num = -1;
59            for entry in entries {
60                let entry = entry?;
61                let file_name = entry.file_name().into_string().unwrap_or_default();
62                if file_name.starts_with("fuzz_") {
63                    let stripped = file_name.strip_prefix("fuzz_").unwrap_or_default();
64                    let num = stripped.parse::<i32>()?;
65                    max_num = max_num.max(num);
66                }
67            }
68            max_num + 1
69        }
70    } else {
71        0
72    }
73}
74#[throws]
75pub async fn collect_program_packages(
76    program_name: Option<String>,
77) -> Vec<cargo_metadata::Package> {
78    let packages: Vec<cargo_metadata::Package> = program_packages(program_name).collect();
79    if packages.is_empty() {
80        throw!(Error::NoProgramsFound)
81    } else {
82        packages
83    }
84}
85pub fn program_packages(
86    program_name: Option<String>,
87) -> Box<dyn Iterator<Item = cargo_metadata::Package>> {
88    let cargo_toml_data = cargo_metadata::MetadataCommand::new()
89        .no_deps()
90        .exec()
91        .expect("Cargo.toml reading failed");
92
93    match program_name {
94        Some(name) => Box::new(
95            cargo_toml_data
96                .packages
97                .into_iter()
98                .filter(move |package| package.name == name),
99        ),
100        None => Box::new(cargo_toml_data.packages.into_iter().filter(|package| {
101            // TODO less error-prone test if the package is a _program_?
102            if let Some("programs") = package.manifest_path.iter().nth_back(2) {
103                return true;
104            }
105            false
106        })),
107    }
108}
109
110// #[throws]
111// pub async fn add_workspace_member(root: &Path, member: &str) {
112//     // Construct the path to the Cargo.toml file
113//     let cargo = root.join("Cargo.toml");
114
115//     // Read and parse the Cargo.toml file
116//     let cargo_toml_content = fs::read_to_string(&cargo).await?;
117//     let mut cargo_toml: Value = toml::from_str(&cargo_toml_content)?;
118
119//     // Ensure that the 'workspace' table exists
120//     let workspace_table = ensure_table(&mut cargo_toml, "workspace")?;
121
122//     // Ensure that the 'members' array exists within the 'workspace' table
123//     let members = workspace_table
124//         .entry("members")
125//         .or_insert(Value::Array(Vec::new()))
126//         .as_array_mut()
127//         .ok_or(Error::CannotParseCargoToml)?;
128
129//     // Check if the new member already exists in the 'members' array
130//     if !members.iter().any(|x| x.as_str() == Some(member)) {
131//         // Add the new member to the 'members' array
132//         members.push(Value::String(member.to_string()));
133//         println!("{FINISH} [{CARGO_TOML}] updated with [{member}]");
134
135//         // Write the updated Cargo.toml back to the file
136//         let updated_toml = toml::to_string(&cargo_toml).unwrap();
137//         fs::write(cargo, updated_toml).await?;
138//     } else {
139//         println!("{SKIP} [{CARGO_TOML}], already contains [{member}]");
140//     }
141// }