Skip to content

Commit 3735c1a

Browse files
authored
Refactor validations and improve error reporting (#27)
Separated validations into individual modules for better modularity. Enhanced ValidationError structure for detailed error reporting, including message and instance path. Updated test cases and references to use the refactored structure.
1 parent 448afef commit 3735c1a

File tree

12 files changed

+447
-308
lines changed

12 files changed

+447
-308
lines changed
Lines changed: 5 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,8 @@
11
use super::schema::CommonSecurityAdvisoryFramework;
2-
use crate::csaf::validation::{test_6_01_01_missing_definition_of_product_id, test_6_01_02_multiple_definition_of_product_id, Test, Validatable, ValidationPreset};
32
use std::collections::HashMap;
3+
use crate::csaf::validation::{Test, Validatable, ValidationPreset};
4+
use crate::csaf::validations::test_6_1_01::test_6_1_01_missing_definition_of_product_id;
5+
use crate::csaf::validations::test_6_1_02::test_6_1_02_multiple_definition_of_product_id;
46

57
impl Validatable<CommonSecurityAdvisoryFramework> for CommonSecurityAdvisoryFramework {
68
fn presets(&self) -> HashMap<ValidationPreset, Vec<&str>> {
@@ -20,8 +22,8 @@ impl Validatable<CommonSecurityAdvisoryFramework> for CommonSecurityAdvisoryFram
2022
fn tests(&self) -> HashMap<&str, Test<CommonSecurityAdvisoryFramework>> {
2123
type CsafTest = Test<CommonSecurityAdvisoryFramework>;
2224
HashMap::from([
23-
("6.1.1", test_6_01_01_missing_definition_of_product_id as CsafTest),
24-
("6.1.2", test_6_01_02_multiple_definition_of_product_id as CsafTest),
25+
("6.1.1", test_6_1_01_missing_definition_of_product_id as CsafTest),
26+
("6.1.2", test_6_1_02_multiple_definition_of_product_id as CsafTest),
2527
])
2628
}
2729

@@ -30,28 +32,3 @@ impl Validatable<CommonSecurityAdvisoryFramework> for CommonSecurityAdvisoryFram
3032
}
3133
}
3234

33-
#[cfg(test)]
34-
mod tests {
35-
use crate::csaf::csaf2_0::loader::load_document;
36-
use crate::csaf::validation::{test_6_01_01_missing_definition_of_product_id, test_6_01_02_multiple_definition_of_product_id};
37-
38-
#[test]
39-
fn test_test_6_01_01() {
40-
let doc = load_document("../csaf/csaf_2.0/test/validator/data/mandatory/oasis_csaf_tc-csaf_2_0-2021-6-1-01-01.json").unwrap();
41-
assert_eq!(
42-
test_6_01_01_missing_definition_of_product_id(&doc),
43-
Err(String::from("Missing definitions: [\"CSAFPID-9080700\", \"CSAFPID-9080701\"]"))
44-
)
45-
}
46-
47-
#[test]
48-
fn test_test_6_01_02() {
49-
let doc = load_document("../csaf/csaf_2.0/test/validator/data/mandatory/oasis_csaf_tc-csaf_2_0-2021-6-1-02-01.json").unwrap();
50-
assert_eq!(
51-
test_6_01_02_multiple_definition_of_product_id(&doc),
52-
Err(String::from(
53-
"Duplicate definitions: [\"CSAFPID-9080700\"]"
54-
))
55-
)
56-
}
57-
}
Lines changed: 9 additions & 75 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,9 @@
11
use super::schema::CommonSecurityAdvisoryFramework;
2-
use crate::csaf::validation::{test_6_01_01_missing_definition_of_product_id, test_6_01_02_multiple_definition_of_product_id, test_6_01_34_branches_recursion_depth, test_6_01_35_contradicting_remediations, Test, Validatable, ValidationPreset};
2+
use crate::csaf::validation::{Test, Validatable, ValidationPreset};
3+
use crate::csaf::validations::test_6_1_01::test_6_1_01_missing_definition_of_product_id;
4+
use crate::csaf::validations::test_6_1_02::test_6_1_02_multiple_definition_of_product_id;
5+
use crate::csaf::validations::test_6_1_34::test_6_1_34_branches_recursion_depth;
6+
use crate::csaf::validations::test_6_1_35::test_6_1_35_contradicting_remediations;
37
use std::collections::HashMap;
48

59
impl Validatable<CommonSecurityAdvisoryFramework> for CommonSecurityAdvisoryFramework {
@@ -20,84 +24,14 @@ impl Validatable<CommonSecurityAdvisoryFramework> for CommonSecurityAdvisoryFram
2024
fn tests(&self) -> HashMap<&str, Test<CommonSecurityAdvisoryFramework>> {
2125
type CsafTest = Test<CommonSecurityAdvisoryFramework>;
2226
HashMap::from([
23-
("6.1.1", test_6_01_01_missing_definition_of_product_id as CsafTest),
24-
("6.1.2", test_6_01_02_multiple_definition_of_product_id as CsafTest),
25-
("6.1.34", test_6_01_34_branches_recursion_depth as CsafTest),
26-
("6.1.35", test_6_01_35_contradicting_remediations as CsafTest),
27+
("6.1.1", test_6_1_01_missing_definition_of_product_id as CsafTest),
28+
("6.1.2", test_6_1_02_multiple_definition_of_product_id as CsafTest),
29+
("6.1.34", test_6_1_34_branches_recursion_depth as CsafTest),
30+
("6.1.35", test_6_1_35_contradicting_remediations as CsafTest),
2731
])
2832
}
2933

3034
fn doc(&self) -> &CommonSecurityAdvisoryFramework {
3135
self
3236
}
3337
}
34-
35-
#[cfg(test)]
36-
mod tests {
37-
use crate::csaf::csaf2_1::loader::load_document;
38-
use crate::csaf::validation::{test_6_01_01_missing_definition_of_product_id, test_6_01_02_multiple_definition_of_product_id, test_6_01_34_branches_recursion_depth, test_6_01_35_contradicting_remediations};
39-
40-
#[test]
41-
fn test_test_6_01_01() {
42-
let doc = load_document("../csaf/csaf_2.1/test/validator/data/mandatory/oasis_csaf_tc-csaf_2_1-2024-6-1-01-01.json").unwrap();
43-
assert_eq!(
44-
test_6_01_01_missing_definition_of_product_id(&doc),
45-
Err(String::from("Missing definitions: [\"CSAFPID-9080700\", \"CSAFPID-9080701\"]"))
46-
)
47-
}
48-
49-
#[test]
50-
fn test_test_6_01_02() {
51-
let doc = load_document("../csaf/csaf_2.1/test/validator/data/mandatory/oasis_csaf_tc-csaf_2_1-2024-6-1-02-01.json").unwrap();
52-
assert_eq!(
53-
test_6_01_02_multiple_definition_of_product_id(&doc),
54-
Err(String::from(
55-
"Duplicate definitions: [\"CSAFPID-9080700\"]"
56-
))
57-
)
58-
}
59-
60-
#[test]
61-
fn test_test_6_01_34() {
62-
for x in ["11"].iter() {
63-
let doc = load_document(format!("../csaf/csaf_2.1/test/validator/data/mandatory/oasis_csaf_tc-csaf_2_1-2024-6-1-34-{}.json", x).as_str()).unwrap();
64-
assert_eq!(
65-
Ok(()),
66-
test_6_01_35_contradicting_remediations(&doc)
67-
)
68-
}
69-
for (x, err) in [
70-
("01", "Branches recursion depth too big (> 30)"),
71-
("02", "Branches recursion depth too big (> 30)"),
72-
].iter() {
73-
let doc = load_document(format!("../csaf/csaf_2.1/test/validator/data/mandatory/oasis_csaf_tc-csaf_2_1-2024-6-1-34-{}.json", x).as_str()).unwrap();
74-
assert_eq!(
75-
Err(format!("{}", err)),
76-
test_6_01_34_branches_recursion_depth(&doc)
77-
)
78-
}
79-
}
80-
81-
#[test]
82-
fn test_test_6_01_35() {
83-
for x in ["11", "12", "13", "14"].iter() {
84-
let doc = load_document(format!("../csaf/csaf_2.1/test/validator/data/mandatory/oasis_csaf_tc-csaf_2_1-2024-6-1-35-{}.json", x).as_str()).unwrap();
85-
assert_eq!(
86-
Ok(()),
87-
test_6_01_35_contradicting_remediations(&doc)
88-
)
89-
}
90-
for (x, err) in [
91-
("01", "Product CSAFPID-9080700 has contradicting remediations: no_fix_planned and vendor_fix"),
92-
("02", "Product CSAFPID-9080700 has contradicting remediations: none_available and mitigation"),
93-
("03", "Product CSAFPID-9080702 has contradicting remediations: workaround, fix_planned and optional_patch"),
94-
("04", "Product CSAFPID-9080701 has contradicting remediations: mitigation, fix_planned and optional_patch"),
95-
].iter() {
96-
let doc = load_document(format!("../csaf/csaf_2.1/test/validator/data/mandatory/oasis_csaf_tc-csaf_2_1-2024-6-1-35-{}.json", x).as_str()).unwrap();
97-
assert_eq!(
98-
Err(format!("{}", err)),
99-
test_6_01_35_contradicting_remediations(&doc)
100-
)
101-
}
102-
}
103-
}

csaf-lib/src/csaf/getter_traits.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -82,12 +82,12 @@ pub trait RemediationTrait {
8282
None
8383
} else {
8484
let mut product_set: BTreeSet<String> = match self.get_product_ids() {
85-
Some(product_ids) => product_ids.iter().map(|p| p.to_string()).collect(),
85+
Some(product_ids) => product_ids.iter().map(|id| (*id).to_owned()).collect(),
8686
None => BTreeSet::new(),
8787
};
8888
if let Some(product_groups) = self.get_group_ids() {
8989
if let Some(product_ids) = resolve_product_groups(doc, product_groups) {
90-
product_set.extend(product_ids.iter().map(|p| p.to_string()));
90+
product_set.extend(product_ids.iter().map(|id| id.to_owned()));
9191
}
9292
}
9393
Some(product_set)

csaf-lib/src/csaf/helpers.rs

Lines changed: 1 addition & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -1,23 +1,5 @@
11
use crate::csaf::getter_traits::{CsafTrait, ProductGroupTrait, ProductTreeTrait};
2-
use std::collections::{BTreeSet, HashMap};
3-
4-
pub fn find_duplicates<T: std::hash::Hash + Eq + Clone>(vec: Vec<T>) -> Vec<T> {
5-
let mut occurrences = HashMap::new();
6-
let mut duplicates = Vec::new();
7-
8-
for item in vec.iter() {
9-
let count = occurrences.entry(item.clone()).or_insert(0);
10-
*count += 1;
11-
}
12-
13-
for (item, count) in occurrences {
14-
if count > 1 {
15-
duplicates.push(item);
16-
}
17-
}
18-
19-
duplicates
20-
}
2+
use std::collections::BTreeSet;
213

224
pub fn resolve_product_groups(doc: &impl CsafTrait, product_groups: Vec<&String>) -> Option<BTreeSet<String>> {
235
doc.get_product_tree().map(|product_tree| {

csaf-lib/src/csaf/mod.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,3 +4,4 @@ mod helpers;
44
pub mod product_helpers;
55
pub mod validation;
66
pub mod getter_traits;
7+
pub mod validations;

0 commit comments

Comments
 (0)