Coverage Report

Created: 2024-02-20 21:15

/builds/xfbs/cindy/common/src/error.rs
Line
Count
Source (jump to first uncovered line)
1
use serde::{Deserialize, Serialize};
2
use std::{
3
    error::Error,
4
    fmt::{Display, Formatter, Result},
5
};
6
7
15
#[derive(
S4
erializ
e4
,
D9
eserialize,
Clone8
,
Debug1
,
P4
artialE
q4
, Eq,
P1
artialOr
d1
,
O0
r
d0
,
Hash3
)]
8
pub struct ErrorResponse {
9
    pub error: String,
10
    pub cause: Option<Box<ErrorResponse>>,
11
}
12
13
impl Display for ErrorResponse {
14
5
    fn fmt(&self, f: &mut Formatter<'_>) -> Result {
15
5
        write!(f, "{}", &self.error)
16
5
    }
17
}
18
19
impl Error for ErrorResponse {
20
4
    fn source(&self) -> Option<&(dyn Error + 'static)> {
21
4
        self.cause
22
4
            .as_ref()
23
4
            .map(|cause| 
cause as &(dyn Error + 'static)3
)
24
4
    }
25
}
26
27
impl ErrorResponse {
28
6
    pub fn new(error: &dyn Error) -> Self {
29
6
        Self {
30
6
            error: error.to_string(),
31
6
            cause: error
32
6
                .source()
33
6
                .map(|error| 
Box::new(ErrorResponse::new(&error))1
),
34
6
        }
35
6
    }
36
}
37
38
#[cfg(test)]
39
mod tests {
40
    use super::*;
41
    use serde_test::{assert_tokens, Token};
42
    use std::io::{Error as IoError, ErrorKind};
43
44
1
    #[test]
45
1
    fn test_serialize() {
46
1
        let error = IoError::new(ErrorKind::NotFound, "not found");
47
1
        assert_tokens(
48
1
            &ErrorResponse::new(&error),
49
1
            &[
50
1
                Token::Struct {
51
1
                    name: "ErrorResponse",
52
1
                    len: 2,
53
1
                },
54
1
                Token::Str("error"),
55
1
                Token::Str("not found"),
56
1
                Token::Str("cause"),
57
1
                Token::None,
58
1
                Token::StructEnd,
59
1
            ],
60
1
        );
61
1
    }
62
63
1
    #[test]
64
1
    fn can_clone() {
65
1
        let response = ErrorResponse {
66
1
            error: "Test".into(),
67
1
            cause: None,
68
1
        };
69
1
        let clone = response.clone();
70
1
        assert_eq!(clone, response);
71
1
        assert_eq!(clone.error, "Test");
72
1
        assert!(clone.cause.is_none());
73
1
    }
74
75
1
    #[test]
76
1
    fn impls_ord_hash() {
77
1
        use std::collections::{BTreeSet, HashSet};
78
1
        let response = ErrorResponse {
79
1
            error: "Test".into(),
80
1
            cause: None,
81
1
        };
82
1
        let other = ErrorResponse {
83
1
            error: "New".into(),
84
1
            cause: Some(response.clone().into()),
85
1
        };
86
1
        let _set: HashSet<_> = [response.clone(), other.clone()].into();
87
1
        let _set: BTreeSet<_> = [response.clone(), other.clone()].into();
88
1
    }
89
90
1
    #[test]
91
1
    fn can_debug() {
92
1
        let response = ErrorResponse {
93
1
            error: "Test".into(),
94
1
            cause: None,
95
1
        };
96
1
        assert!(format!("{response:?}").len() > 0);
97
1
    }
98
99
1
    #[test]
100
1
    fn can_display() {
101
1
        let response = ErrorResponse {
102
1
            error: "Test".into(),
103
1
            cause: None,
104
1
        };
105
1
        assert_eq!(format!("{response}"), "Test");
106
1
    }
107
108
1
    #[test]
109
1
    fn can_error() {
110
1
        let root = ErrorResponse {
111
1
            error: "Root".into(),
112
1
            cause: None,
113
1
        };
114
1
        let response = ErrorResponse {
115
1
            error: "Test".into(),
116
1
            cause: Some(root.into()),
117
1
        };
118
1
119
1
        assert_eq!(response.to_string(), "Test");
120
1
        assert_eq!(response.source().unwrap().to_string(), "Root");
121
1
        assert_eq!(response.source().unwrap().source().is_none(), true);
122
1
    }
123
124
1
    #[test]
125
1
    fn can_new() {
126
1
        let error = anyhow::anyhow!("error").context("something");
127
1
        let error_response = ErrorResponse::new(error.as_ref());
128
1
        assert_eq!(error_response.to_string(), "something");
129
1
        assert_eq!(error_response.source().unwrap().to_string(), "error");
130
1
    }
131
}