Skip to content

Commit 5546f18

Browse files
committed
More common 2.0/2.1 validation code
1 parent 3265cb9 commit 5546f18

File tree

12 files changed

+150
-124
lines changed

12 files changed

+150
-124
lines changed

Cargo.lock

Lines changed: 0 additions & 7 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

csaf

Submodule csaf updated 46 files

csaf-lib/Cargo.toml

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,6 @@ regress = "0.10.1"
88
serde = { version = "1.0", features = ["derive"] }
99
serde_json = "1.0"
1010
chrono = { version = "0.4.38", features = ["serde"] }
11-
lazy_static = "1.5.0"
1211

1312
[build-dependencies]
1413
schemars = "0.8.21"

csaf-lib/src/csaf/csaf2_0/loader.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
1-
use std::{fs::File, io::BufReader};
2-
31
use super::schema::CommonSecurityAdvisoryFramework;
2+
use crate::csaf::validation::Validatable;
3+
use std::{fs::File, io::BufReader};
44

55
pub fn load_document(path: &str) -> std::io::Result<CommonSecurityAdvisoryFramework> {
66
println!("Trying to load document {}", path);

csaf-lib/src/csaf/csaf2_0/validation.rs

Lines changed: 19 additions & 38 deletions
Original file line numberDiff line numberDiff line change
@@ -1,29 +1,28 @@
11
use super::product_helper::*;
22
use super::schema::CommonSecurityAdvisoryFramework;
3-
use crate::csaf::validation::{Validate, ValidationProfile};
3+
use crate::csaf::validation::{Test, Validatable, Validate, ValidationProfile};
44
use std::collections::{HashMap, HashSet};
5+
use crate::csaf::helpers::find_duplicates;
6+
7+
impl Validatable<CommonSecurityAdvisoryFramework> for CommonSecurityAdvisoryFramework {
8+
fn profiles(&self) -> HashMap<ValidationProfile, Vec<&str>> {
9+
HashMap::from([
10+
(ValidationProfile::Basic, Vec::from(["6.1.1", "6.1.2"])),
11+
(ValidationProfile::Extended, Vec::from(["6.1.1", "6.1.2"])),
12+
(ValidationProfile::Full, Vec::from(["6.1.1", "6.1.2"])),
13+
])
14+
}
515

6-
impl Validate for CommonSecurityAdvisoryFramework {
7-
fn validate_profile(&self, profile: ValidationProfile) {
8-
println!("Validating document... \n");
9-
10-
println!("Executing Test 6.1.1... ");
11-
12-
let _ = match test_6_01_01_missing_definition_of_product_id(self) {
13-
Ok(()) => println!("> Test Success"),
14-
Err(e) => println!("> Error: {}", e),
15-
};
16-
17-
println!("Executing Test 6.1.2... ");
18-
19-
let _ = match test_6_01_02_multiple_definition_of_product_id(self) {
20-
Ok(()) => println!("> Test Success"),
21-
Err(e) => println!("> Error: {}", e),
22-
};
16+
fn tests(&self) -> HashMap<&str, Test<CommonSecurityAdvisoryFramework>> {
17+
HashMap::<&str, Test<CommonSecurityAdvisoryFramework>>::from([
18+
("6.1.1", test_6_01_01_missing_definition_of_product_id),
19+
("6.1.2", test_6_01_02_multiple_definition_of_product_id),
20+
]
21+
as [(&str, Test<CommonSecurityAdvisoryFramework>); 2])
2322
}
2423

25-
fn validate_by_test(&self, version: &str) {
26-
todo!()
24+
fn doc(&self) -> &CommonSecurityAdvisoryFramework {
25+
self
2726
}
2827
}
2928

@@ -56,24 +55,6 @@ pub fn test_6_01_02_multiple_definition_of_product_id(
5655
}
5756
}
5857

59-
fn find_duplicates<T: std::hash::Hash + Eq + Clone>(vec: Vec<T>) -> Vec<T> {
60-
let mut occurrences = HashMap::new();
61-
let mut duplicates = Vec::new();
62-
63-
for item in vec.iter() {
64-
let count = occurrences.entry(item.clone()).or_insert(0);
65-
*count += 1;
66-
}
67-
68-
for (item, count) in occurrences {
69-
if count > 1 {
70-
duplicates.push(item);
71-
}
72-
}
73-
74-
duplicates
75-
}
76-
7758
#[cfg(test)]
7859
mod tests {
7960
use crate::csaf::csaf2_0::validation::test_6_01_02_multiple_definition_of_product_id;

csaf-lib/src/csaf/csaf2_1/loader.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
use std::{fs::File, io::BufReader};
2-
2+
use crate::csaf::validation::Validatable;
33
use super::schema::CommonSecurityAdvisoryFramework;
44

55
pub fn load_document(path: &str) -> std::io::Result<CommonSecurityAdvisoryFramework> {

csaf-lib/src/csaf/csaf2_1/product_helper.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
use super::schema::{Branch, BranchesT, CommonSecurityAdvisoryFramework, ProductIdT, ProductTree};
1+
use super::schema::{Branch, CommonSecurityAdvisoryFramework, ProductIdT, ProductTree};
22
use std::collections::HashSet;
33

44
pub fn gather_product_references(doc: &CommonSecurityAdvisoryFramework) -> HashSet<&ProductIdT> {
@@ -93,7 +93,7 @@ pub fn gather_product_definitions_from_branch(branch: &Branch) -> Vec<&ProductId
9393
}
9494

9595
pub fn count_branch_depth(branch: &Branch) -> u32 {
96-
let mut i = 0;
96+
let mut i = 1;
9797

9898
// Go into the branch, calculate the depth and take the maximum value
9999
if let Some(x) = branch.branches.as_ref() {
Lines changed: 36 additions & 64 deletions
Original file line numberDiff line numberDiff line change
@@ -1,48 +1,32 @@
11
use super::product_helper::*;
22
use super::schema::CommonSecurityAdvisoryFramework;
3-
use crate::csaf::validation::{Validate, ValidationProfile};
4-
use lazy_static::lazy_static;
3+
use crate::csaf::helpers::find_duplicates;
4+
use crate::csaf::validation::{Test, Validatable, Validate, ValidationProfile};
55
use std::collections::{HashMap, HashSet};
66

7-
type Test = fn(&CommonSecurityAdvisoryFramework) -> Result<(), String>;
8-
9-
// TODO: convert this to code using std::sync::OnceLock
10-
lazy_static! {
11-
static ref PROFILES: HashMap<ValidationProfile, Vec<&'static str>> = HashMap::from([
12-
(
13-
ValidationProfile::Basic,
14-
Vec::from(["6.1.1", "6.1.2", "6.1.34"])
15-
),
16-
(ValidationProfile::Extended, Vec::from(["6.1.1", "6.1.2"])),
17-
(ValidationProfile::Full, Vec::from(["6.1.1", "6.1.2"])),
18-
]);
19-
static ref TESTS: HashMap<&'static str, Test> = HashMap::<&str, Test>::from([
20-
("6.1.1", test_6_01_01_missing_definition_of_product_id),
21-
("6.1.2", test_6_01_02_multiple_definition_of_product_id),
22-
] as [(&str, Test); 2]);
23-
}
24-
25-
impl Validate for CommonSecurityAdvisoryFramework {
26-
fn validate_profile(&self, profile: ValidationProfile) {
27-
println!("Validating document... \n");
28-
29-
println!("Executing Test 6.1.1... ");
30-
31-
let _ = match test_6_01_01_missing_definition_of_product_id(self) {
32-
Ok(()) => println!("> Test Success"),
33-
Err(e) => println!("> Error: {}", e),
34-
};
35-
36-
println!("Executing Test 6.1.2... ");
7+
impl Validatable<CommonSecurityAdvisoryFramework> for CommonSecurityAdvisoryFramework {
8+
fn profiles(&self) -> HashMap<ValidationProfile, Vec<&str>> {
9+
HashMap::from([
10+
(
11+
ValidationProfile::Basic,
12+
Vec::from(["6.1.1", "6.1.2", "6.1.34"]),
13+
),
14+
(ValidationProfile::Extended, Vec::from(["6.1.1", "6.1.2"])),
15+
(ValidationProfile::Full, Vec::from(["6.1.1", "6.1.2"])),
16+
])
17+
}
3718

38-
let _ = match test_6_01_02_multiple_definition_of_product_id(self) {
39-
Ok(()) => println!("> Test Success"),
40-
Err(e) => println!("> Error: {}", e),
41-
};
19+
fn tests(&self) -> HashMap<&str, Test<CommonSecurityAdvisoryFramework>> {
20+
HashMap::<&str, Test<CommonSecurityAdvisoryFramework>>::from([
21+
("6.1.1", test_6_01_01_missing_definition_of_product_id),
22+
("6.1.2", test_6_01_02_multiple_definition_of_product_id),
23+
("6.1.34", test_6_01_34_branches_recursion_depth),
24+
]
25+
as [(&str, Test<CommonSecurityAdvisoryFramework>); 3])
4226
}
4327

44-
fn validate_by_test(&self, version: &str) {
45-
todo!()
28+
fn doc(&self) -> &CommonSecurityAdvisoryFramework {
29+
self
4630
}
4731
}
4832

@@ -62,10 +46,6 @@ pub fn test_6_01_01_missing_definition_of_product_id(
6246
}
6347
}
6448

65-
pub fn testbla(doc: &CommonSecurityAdvisoryFramework) -> Result<(), String> {
66-
Ok(())
67-
}
68-
6949
pub fn test_6_01_02_multiple_definition_of_product_id(
7050
doc: &CommonSecurityAdvisoryFramework,
7151
) -> Result<(), String> {
@@ -95,34 +75,17 @@ pub fn test_6_01_34_branches_recursion_depth(
9575
}
9676
}
9777

98-
fn find_duplicates<T: std::hash::Hash + Eq + Clone>(vec: Vec<T>) -> Vec<T> {
99-
let mut occurrences = HashMap::new();
100-
let mut duplicates = Vec::new();
101-
102-
for item in vec.iter() {
103-
let count = occurrences.entry(item.clone()).or_insert(0);
104-
*count += 1;
105-
}
106-
107-
for (item, count) in occurrences {
108-
if count > 1 {
109-
duplicates.push(item);
110-
}
111-
}
112-
113-
duplicates
114-
}
115-
11678
#[cfg(test)]
11779
mod tests {
118-
use crate::csaf::csaf2_0::validation::test_6_01_02_multiple_definition_of_product_id;
119-
use crate::csaf::csaf2_0::{
80+
use crate::csaf::csaf2_1::{
12081
loader::load_document, validation::test_6_01_01_missing_definition_of_product_id,
82+
validation::test_6_01_02_multiple_definition_of_product_id,
83+
validation::test_6_01_34_branches_recursion_depth,
12184
};
12285

12386
#[test]
12487
fn test_test_6_01_01() {
125-
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();
88+
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();
12689
assert_eq!(
12790
test_6_01_01_missing_definition_of_product_id(&doc),
12891
Err(String::from("Missing definitions: [ProductIdT(\"CSAFPID-9080700\"), ProductIdT(\"CSAFPID-9080701\")]"))
@@ -131,12 +94,21 @@ mod tests {
13194

13295
#[test]
13396
fn test_test_6_01_02() {
134-
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();
97+
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();
13598
assert_eq!(
13699
test_6_01_02_multiple_definition_of_product_id(&doc),
137100
Err(String::from(
138101
"Duplicate definitions: [ProductIdT(\"CSAFPID-9080700\")]"
139102
))
140103
)
141104
}
105+
106+
#[test]
107+
fn test_test_6_01_34() {
108+
let doc = load_document("../csaf/csaf_2.1/test/validator/data/mandatory/oasis_csaf_tc-csaf_2_1-2024-6-1-34-01.json").unwrap();
109+
assert_eq!(
110+
test_6_01_34_branches_recursion_depth(&doc),
111+
Err(String::from("Recursion depth too big: 31"))
112+
)
113+
}
142114
}

csaf-lib/src/csaf/helpers.rs

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

csaf-lib/src/csaf/mod.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
11
pub mod csaf2_0;
22
pub mod csaf2_1;
3+
mod helpers;
34
pub mod validation;

0 commit comments

Comments
 (0)