use crate::config::module_path::ModulePath;
use crate::config::rust_file_finder::RustFileFinder;
use crate::config::test_name_reader::TestNameReader;
use std::fs::read_to_string;
use std::path::PathBuf;
pub struct TestPathScanner;
impl TestPathScanner {
pub fn scan(roots: &[PathBuf]) -> Result<Vec<String>, String> {
let mut names = Vec::new();
for root in roots {
if !root.exists() {
return Err(format!("--jobs-path {} does not exist", root.display()));
}
for file in RustFileFinder::under(root)? {
let module = ModulePath::of(root, &file);
let contents = read_to_string(&file)
.map_err(|error| format!("{} could not be read: {error}", file.display()))?;
names.extend(
TestNameReader::names_in(&contents)
.into_iter()
.map(|test| Self::qualified(&module, &test)),
);
}
}
if names.is_empty() {
return Err(format!(
"--jobs-path found no tests under {}",
Self::listed(roots)
));
}
names.sort();
names.dedup();
Ok(names)
}
fn listed(roots: &[PathBuf]) -> String {
roots
.iter()
.map(|root| root.display().to_string())
.collect::<Vec<_>>()
.join(", ")
}
fn qualified(module: &str, test: &str) -> String {
if module.is_empty() {
test.to_string()
} else {
format!("{module}::{test}")
}
}
}