#[cfg(test)]
mod tests {
use super::super::PackageParser;
use super::super::cran::CranParser;
use crate::models::DatasourceId;
use crate::models::PackageType;
use std::path::PathBuf;
#[test]
fn test_is_match() {
let valid_path = PathBuf::from("/some/path/DESCRIPTION");
let invalid_path = PathBuf::from("/some/path/description");
let another_invalid = PathBuf::from("/some/path/DESCRIPTION.txt");
assert!(CranParser::is_match(&valid_path));
assert!(!CranParser::is_match(&invalid_path));
assert!(!CranParser::is_match(&another_invalid));
}
#[test]
fn test_extract_from_testdata_geometry() {
let desc_path = PathBuf::from("testdata/cran/geometry/DESCRIPTION");
let package_data = CranParser::extract_first_package(&desc_path);
assert_eq!(package_data.package_type, Some(PackageType::Cran));
assert_eq!(package_data.name, Some("geometry".to_string()));
assert_eq!(package_data.version, Some("0.4.2".to_string()));
assert_eq!(package_data.primary_language, Some("R".to_string()));
assert_eq!(
package_data.extracted_license_statement,
Some("GPL (>= 3)".to_string())
);
assert_eq!(
package_data.purl,
Some("pkg:cran/geometry@0.4.2".to_string())
);
assert_eq!(
package_data.repository_homepage_url,
Some("https://cran.r-project.org/package=geometry".to_string())
);
assert_eq!(
package_data.homepage_url,
Some("https://davidcsterratt.github.io/geometry".to_string())
);
assert!(package_data.description.is_some());
let desc = package_data.description.unwrap();
assert!(desc.contains("Mesh Generation and Surface Tessellation"));
assert!(desc.contains("Qhull"));
assert_eq!(package_data.dependencies.len(), 11);
let imports: Vec<_> = package_data
.dependencies
.iter()
.filter(|d| d.scope == Some("imports".to_string()))
.collect();
assert_eq!(imports.len(), 4);
let suggests: Vec<_> = package_data
.dependencies
.iter()
.filter(|d| d.scope == Some("suggests".to_string()))
.collect();
assert_eq!(suggests.len(), 5);
let linking_to: Vec<_> = package_data
.dependencies
.iter()
.filter(|d| d.scope == Some("linkingto".to_string()))
.collect();
assert_eq!(linking_to.len(), 2);
for dep in &imports {
assert_eq!(dep.is_runtime, Some(true));
assert_eq!(dep.is_optional, Some(false));
}
for dep in &suggests {
assert_eq!(dep.is_optional, Some(true));
}
assert!(!package_data.parties.is_empty());
let maintainers: Vec<_> = package_data
.parties
.iter()
.filter(|p| p.role == Some("maintainer".to_string()))
.collect();
assert_eq!(maintainers.len(), 1);
assert_eq!(maintainers[0].name, Some("David C. Sterratt".to_string()));
assert_eq!(
maintainers[0].email,
Some("david.c.sterratt@ed.ac.uk".to_string())
);
let authors: Vec<_> = package_data
.parties
.iter()
.filter(|p| p.role == Some("author".to_string()))
.collect();
assert!(!authors.is_empty());
}
#[test]
fn test_extract_from_testdata_codetools() {
let desc_path = PathBuf::from("testdata/cran/codetools/DESCRIPTION");
let package_data = CranParser::extract_first_package(&desc_path);
assert_eq!(package_data.name, Some("codetools".to_string()));
assert_eq!(package_data.version, Some("0.2-16".to_string()));
assert_eq!(
package_data.extracted_license_statement,
Some("GPL".to_string())
);
assert!(package_data.description.is_some());
let desc = package_data.description.unwrap();
assert!(desc.contains("Code Analysis Tools for R"));
assert!(desc.contains("Code analysis tools for R"));
assert_eq!(package_data.dependencies.len(), 0);
let maintainers: Vec<_> = package_data
.parties
.iter()
.filter(|p| p.role == Some("maintainer".to_string()))
.collect();
assert_eq!(maintainers.len(), 1);
assert_eq!(maintainers[0].name, Some("Luke Tierney".to_string()));
assert_eq!(
maintainers[0].email,
Some("luke-tierney@uiowa.edu".to_string())
);
let authors: Vec<_> = package_data
.parties
.iter()
.filter(|p| p.role == Some("author".to_string()))
.collect();
assert_eq!(authors.len(), 1);
assert_eq!(authors[0].name, Some("Luke Tierney".to_string()));
}
#[test]
fn test_dependencies_with_versions() {
let desc_path = PathBuf::from("testdata/cran/geometry/DESCRIPTION");
let package_data = CranParser::extract_first_package(&desc_path);
for dep in &package_data.dependencies {
assert_eq!(dep.is_pinned, Some(false));
assert!(dep.extracted_requirement.is_none());
}
}
#[test]
fn test_filter_r_version() {
let desc_path = PathBuf::from("testdata/cran/geometry/DESCRIPTION");
let package_data = CranParser::extract_first_package(&desc_path);
for dep in &package_data.dependencies {
if let Some(ref purl) = dep.purl {
assert!(!purl.starts_with("pkg:cran/R@"));
assert!(purl != "pkg:cran/R");
}
}
}
#[test]
fn test_multiple_dependency_types() {
let desc_path = PathBuf::from("testdata/cran/geometry/DESCRIPTION");
let package_data = CranParser::extract_first_package(&desc_path);
let scopes: std::collections::HashSet<_> = package_data
.dependencies
.iter()
.filter_map(|d| d.scope.as_ref())
.collect();
assert!(scopes.contains(&"imports".to_string()));
assert!(scopes.contains(&"suggests".to_string()));
assert!(scopes.contains(&"linkingto".to_string()));
}
#[test]
fn test_author_maintainer_parsing() {
let desc_path = PathBuf::from("testdata/cran/codetools/DESCRIPTION");
let package_data = CranParser::extract_first_package(&desc_path);
let maintainers: Vec<_> = package_data
.parties
.iter()
.filter(|p| p.role == Some("maintainer".to_string()))
.collect();
assert_eq!(maintainers.len(), 1);
assert!(maintainers[0].name.is_some());
assert!(maintainers[0].email.is_some());
let authors: Vec<_> = package_data
.parties
.iter()
.filter(|p| p.role == Some("author".to_string()))
.collect();
assert_eq!(authors.len(), 1);
assert!(authors[0].name.is_some());
}
#[test]
fn test_empty_description() {
let nonexistent_path = PathBuf::from("testdata/cran/nonexistent/DESCRIPTION");
let package_data = CranParser::extract_first_package(&nonexistent_path);
assert_eq!(package_data.package_type, Some(PackageType::Cran));
assert_eq!(
package_data.datasource_id,
Some(DatasourceId::CranDescription)
);
assert_eq!(package_data.primary_language, Some("R".to_string()));
assert!(package_data.name.is_none());
assert!(package_data.version.is_none());
}
#[test]
fn test_purl_generation() {
let desc_path = PathBuf::from("testdata/cran/codetools/DESCRIPTION");
let package_data = CranParser::extract_first_package(&desc_path);
assert_eq!(
package_data.purl,
Some("pkg:cran/codetools@0.2-16".to_string())
);
for dep in &package_data.dependencies {
if let Some(ref purl) = dep.purl {
assert!(purl.starts_with("pkg:cran/"));
}
}
}
}