use bole::pm::{Category, PmInfo, all_package_managers};
use rayon::prelude::*;
pub(crate) struct Discovery {
categories: Vec<Category>,
}
impl Discovery {
pub(crate) fn all() -> Self {
Self {
categories: Category::all().to_vec(),
}
}
pub(crate) fn from_optional_category(category: Option<String>) -> Self {
category
.and_then(|cat_str| Self::parse_category(&cat_str))
.map(|cat| Self {
categories: vec![cat],
})
.unwrap_or_else(Self::all) }
pub(crate) fn discover(&self) -> Vec<PmInfo> {
all_package_managers()
.into_par_iter()
.filter(|d| self.categories.contains(&d.category()))
.flat_map(|detector| detector.find())
.collect()
}
fn parse_category(input: &str) -> Option<Category> {
let lower = input.to_lowercase();
for &category in Category::all() {
if lower == category.name() {
return Some(category);
}
for &alias in category.aliases() {
if lower == alias {
return Some(category);
}
}
}
None
}
pub(crate) fn is_valid_category(input: &str) -> bool {
Self::parse_category(input).is_some()
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_discovery_all() {
let discovery = Discovery::all();
assert_eq!(discovery.categories.len(), Category::all().len());
}
#[test]
fn test_from_optional_category_none() {
let category_input: Option<String> = None;
let discovery = Discovery::from_optional_category(category_input);
assert_eq!(discovery.categories.len(), Category::all().len());
}
#[test]
fn test_from_optional_category_valid() {
let category_input = Some("system".to_string());
let discovery = Discovery::from_optional_category(category_input);
assert_eq!(discovery.categories, vec![Category::System]);
}
#[test]
fn test_from_optional_category_valid_alias() {
let category_input = Some("js".to_string());
let discovery = Discovery::from_optional_category(category_input);
assert_eq!(discovery.categories, vec![Category::JavaScript]);
}
#[test]
fn test_from_optional_category_case_insensitive() {
let category_input = Some("PYTHON".to_string());
let discovery = Discovery::from_optional_category(category_input);
assert_eq!(discovery.categories, vec![Category::Python]);
}
#[test]
fn test_from_optional_category_invalid() {
let invalid_category = Some("invalid".to_string());
let discovery = Discovery::from_optional_category(invalid_category);
assert_eq!(discovery.categories.len(), Category::all().len());
}
#[test]
fn test_discover() {
let discovery = Discovery {
categories: vec![Category::System],
};
let result = discovery.discover();
assert!(result.is_empty() || !result.is_empty());
}
#[test]
fn test_discover_all_categories() {
let discovery = Discovery::all();
let result = discovery.discover();
assert!(result.is_empty() || !result.is_empty());
}
#[test]
fn test_parse_category_all_categories() {
for &category in Category::all() {
assert!(Discovery::is_valid_category(category.name()));
}
}
#[test]
fn test_is_valid_category() {
assert!(Discovery::is_valid_category("system"));
assert!(Discovery::is_valid_category("javascript"));
assert!(Discovery::is_valid_category("SYSTEM"));
assert!(Discovery::is_valid_category("JavaScript"));
assert!(Discovery::is_valid_category("sys"));
assert!(Discovery::is_valid_category("js"));
assert!(!Discovery::is_valid_category(""));
assert!(!Discovery::is_valid_category("not-a-category"));
}
}