use crate::csaf::types::csaf_document_category::CsafDocumentCategory;
use crate::csaf_traits::CsafVersion;
#[derive(Debug, Clone, PartialEq, Default)]
pub struct DocumentCategoryTestConfig {
pub shared_categories: Option<&'static [CsafDocumentCategory]>,
pub csaf20_categories: Option<&'static [CsafDocumentCategory]>,
pub csaf21_categories: Option<&'static [CsafDocumentCategory]>,
}
impl DocumentCategoryTestConfig {
pub const fn new() -> Self {
Self {
shared_categories: None,
csaf20_categories: None,
csaf21_categories: None,
}
}
pub const fn shared(mut self, categories: &'static [CsafDocumentCategory]) -> Self {
self.shared_categories = Some(categories);
self
}
#[allow(dead_code)]
pub const fn csaf20(mut self, categories: &'static [CsafDocumentCategory]) -> Self {
self.csaf20_categories = Some(categories);
self
}
pub const fn csaf21(mut self, categories: &'static [CsafDocumentCategory]) -> Self {
self.csaf21_categories = Some(categories);
self
}
pub fn matches_category_with_csaf_version(
&self,
csaf_version: CsafVersion,
document_category: &CsafDocumentCategory,
) -> bool {
if let Some(shared) = self.shared_categories
&& shared.contains(document_category)
{
return true;
}
match csaf_version {
CsafVersion::X20 => self
.csaf20_categories
.map(|cats| cats.contains(document_category))
.unwrap_or_else(|| {
if self.shared_categories.is_none() {
panic!("Test applicability was checked for CSAF 2.0 on a config that does not contain CSAF 2.0-specific categories or shared categories. (This looks like a dev error)")
}
false
}),
CsafVersion::X21 => self
.csaf21_categories
.map(|cats| cats.contains(document_category))
.unwrap_or_else(|| {
if self.shared_categories.is_none() {
panic!("Test applicability was checked for CSAF 2.1 on a config that does not contain CSAF 2.1-specific categories or shared categories. (This looks like a dev error.)")
}
false
}),
}
}
pub fn matches_category(&self, document_category: &CsafDocumentCategory) -> bool {
if let Some(shared) = self.shared_categories {
return shared.contains(document_category);
}
panic!(
"Test applicability without a specified CSAF doc version was checked on a config that does not specify version-independent categories. (This looks like a dev error.)"
);
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_config_with_csaf20_csaf_21_specific_categories() {
const TEST_CONFIG: DocumentCategoryTestConfig = DocumentCategoryTestConfig::new()
.shared(&[CsafDocumentCategory::CsafSecurityAdvisory])
.csaf20(&[CsafDocumentCategory::CsafVex])
.csaf21(&[CsafDocumentCategory::CsafWithdrawn]);
assert!(
TEST_CONFIG
.matches_category_with_csaf_version(CsafVersion::X20, &CsafDocumentCategory::CsafSecurityAdvisory)
);
assert!(
TEST_CONFIG
.matches_category_with_csaf_version(CsafVersion::X21, &CsafDocumentCategory::CsafSecurityAdvisory)
);
assert!(TEST_CONFIG.matches_category_with_csaf_version(CsafVersion::X20, &CsafDocumentCategory::CsafVex));
assert!(!TEST_CONFIG.matches_category_with_csaf_version(CsafVersion::X21, &CsafDocumentCategory::CsafVex));
assert!(
!TEST_CONFIG.matches_category_with_csaf_version(CsafVersion::X20, &CsafDocumentCategory::CsafWithdrawn)
);
assert!(TEST_CONFIG.matches_category_with_csaf_version(CsafVersion::X21, &CsafDocumentCategory::CsafWithdrawn));
assert!(
!TEST_CONFIG
.matches_category_with_csaf_version(CsafVersion::X20, &CsafDocumentCategory::CsafInformationalAdvisory)
);
assert!(
!TEST_CONFIG
.matches_category_with_csaf_version(CsafVersion::X21, &CsafDocumentCategory::CsafInformationalAdvisory)
);
}
#[test]
fn test_config_with_only_shared_categories() {
const TEST_CONFIG: DocumentCategoryTestConfig = DocumentCategoryTestConfig::new().shared(&[
CsafDocumentCategory::CsafSecurityAdvisory,
CsafDocumentCategory::CsafInformationalAdvisory,
]);
assert!(TEST_CONFIG.matches_category(&CsafDocumentCategory::CsafSecurityAdvisory));
assert!(TEST_CONFIG.matches_category(&CsafDocumentCategory::CsafInformationalAdvisory));
assert!(!TEST_CONFIG.matches_category(&CsafDocumentCategory::CsafVex));
assert!(!TEST_CONFIG.matches_category(&CsafDocumentCategory::CsafWithdrawn));
}
#[test]
fn test_config_without_shared_categories_panic_on_is_ignored_for() {
const TEST_CONFIG: DocumentCategoryTestConfig = DocumentCategoryTestConfig::new()
.csaf20(&[CsafDocumentCategory::CsafVex])
.csaf21(&[CsafDocumentCategory::CsafWithdrawn]);
let result = std::panic::catch_unwind(|| {
TEST_CONFIG.matches_category(&CsafDocumentCategory::CsafSecurityAdvisory);
});
assert!(result.is_err());
}
#[test]
fn test_config_without_shared_or_csaf_20_categories_panics_on_is_ignored_for_on_csaf_version() {
const TEST_CONFIG: DocumentCategoryTestConfig =
DocumentCategoryTestConfig::new().csaf21(&[CsafDocumentCategory::CsafWithdrawn]);
let result = std::panic::catch_unwind(|| {
TEST_CONFIG.matches_category_with_csaf_version(CsafVersion::X20, &CsafDocumentCategory::CsafVex);
});
assert!(result.is_err());
}
#[test]
fn test_config_without_shared_or_csaf_21_categories_panics_on_is_ignored_for_on_csaf_version() {
const TEST_CONFIG: DocumentCategoryTestConfig =
DocumentCategoryTestConfig::new().csaf20(&[CsafDocumentCategory::CsafVex]);
let result = std::panic::catch_unwind(|| {
TEST_CONFIG.matches_category_with_csaf_version(CsafVersion::X21, &CsafDocumentCategory::CsafWithdrawn);
});
assert!(result.is_err());
}
}