Skip to main content

harbor_core/
analysis_result.rs

1use crate::severity::Severity;
2
3/// Represents the result of a security analysis check.
4#[derive(Debug, Clone)]
5pub struct AnalysisResult {
6    pub severity: Severity,
7    pub name: String,
8    pub comment: String,
9    /// Score impact for this result. Negative values are penalties deducted
10    /// from the baseline; positive values are bonuses added when score >= 90.
11    pub score_impact: i32,
12}
13
14impl AnalysisResult {
15    pub fn new(
16        severity: Severity,
17        name: impl Into<String>,
18        comment: impl Into<String>,
19    ) -> Self {
20        Self {
21            severity,
22            name: name.into(),
23            comment: comment.into(),
24            score_impact: 0,
25        }
26    }
27
28    /// Set the score impact for this result.
29    pub fn with_score(mut self, score_impact: i32) -> Self {
30        self.score_impact = score_impact;
31        self
32    }
33}
34
35#[cfg(test)]
36mod tests {
37    use super::*;
38
39    #[test]
40    fn new_creates_result_with_correct_fields() {
41        let result = AnalysisResult::new(Severity::Ok, "Test Name", "Test Comment");
42        assert_eq!(result.severity, Severity::Ok);
43        assert_eq!(result.name, "Test Name");
44        assert_eq!(result.comment, "Test Comment");
45        assert_eq!(result.score_impact, 0);
46    }
47
48    #[test]
49    fn new_accepts_owned_strings() {
50        let name = String::from("Owned Name");
51        let comment = String::from("Owned Comment");
52        let result = AnalysisResult::new(Severity::Fail, name, comment);
53        assert_eq!(result.name, "Owned Name");
54        assert_eq!(result.comment, "Owned Comment");
55    }
56
57    #[test]
58    fn with_score_sets_score_impact() {
59        let result = AnalysisResult::new(Severity::Ok, "Name", "Comment").with_score(10);
60        assert_eq!(result.score_impact, 10);
61    }
62
63    #[test]
64    fn with_score_accepts_negative_values() {
65        let result = AnalysisResult::new(Severity::Fail, "Name", "Comment").with_score(-25);
66        assert_eq!(result.score_impact, -25);
67    }
68
69    #[test]
70    fn clone_produces_independent_copy() {
71        let original = AnalysisResult::new(Severity::Warning, "Name", "Comment").with_score(-5);
72        let cloned = original.clone();
73        assert_eq!(original.severity, cloned.severity);
74        assert_eq!(original.name, cloned.name);
75        assert_eq!(original.comment, cloned.comment);
76        assert_eq!(original.score_impact, cloned.score_impact);
77    }
78}