Skip to content

Commit 64f79d1

Browse files
committed
Refactor validations and improve error reporting
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 64f79d1

File tree

13 files changed

+449
-310
lines changed

13 files changed

+449
-310
lines changed
Lines changed: 6 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,13 @@
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>> {
79
let basic_tests = Vec::from(["6.1.1", "6.1.2"]);
8-
// More tests may be added in extend() here later
10+
// More validations may be added in extend() here later
911
let extended_tests: Vec<&str> = basic_tests.clone();
1012
// extended_tests.extend(["foo"].iter());
1113
let full_tests: Vec<&str> = extended_tests.clone();
@@ -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)