Skip to main content

alpine/
error.rs

1use thiserror::Error;
2
3#[derive(Debug, Error)]
4pub enum ProviderError {
5    #[error("HTTP error: {0}")]
6    Http(#[from] reqwest::Error),
7
8    #[error("JSON serialization error: {0}")]
9    Json(#[from] serde_json::Error),
10
11    #[error("API error ({status}): {message}")]
12    Api { status: u16, message: String },
13
14    #[error("Stream error: {0}")]
15    Stream(String),
16
17    #[error("Unsupported operation: {0}")]
18    Unsupported(String),
19
20    #[error("{0}")]
21    Other(String),
22}
23
24#[cfg(test)]
25mod tests {
26    use super::*;
27
28    #[test]
29    fn api_error_display() {
30        let e = ProviderError::Api {
31            status: 429,
32            message: "rate limit".into(),
33        };
34        let s = e.to_string();
35        assert!(s.contains("429"));
36        assert!(s.contains("rate limit"));
37    }
38
39    #[test]
40    fn stream_error_display() {
41        let e = ProviderError::Stream("broken pipe".into());
42        assert!(e.to_string().contains("broken pipe"));
43    }
44
45    #[test]
46    fn unsupported_display() {
47        let e = ProviderError::Unsupported("embed".into());
48        assert!(e.to_string().contains("embed"));
49    }
50
51    #[test]
52    fn other_display() {
53        let e = ProviderError::Other("oops".into());
54        assert_eq!(e.to_string(), "oops");
55    }
56
57    #[test]
58    fn json_error_from_serde() {
59        let err = serde_json::from_str::<serde_json::Value>("not json").unwrap_err();
60        let pe = ProviderError::from(err);
61        assert!(pe.to_string().contains("JSON serialization error"));
62    }
63
64    #[test]
65    fn http_error_from_reqwest() {
66        // Build a reqwest error by sending to an invalid URL
67        let rt = tokio::runtime::Runtime::new().unwrap();
68        let err = rt.block_on(async { reqwest::get("http://[::0]:0/invalid").await.unwrap_err() });
69        let pe = ProviderError::from(err);
70        assert!(pe.to_string().contains("HTTP error"));
71    }
72
73    #[test]
74    fn error_is_std_error() {
75        let e: Box<dyn std::error::Error> = Box::new(ProviderError::Other("x".into()));
76        assert!(e.source().is_none());
77
78        let json_err = serde_json::from_str::<serde_json::Value>("bad").unwrap_err();
79        let e: Box<dyn std::error::Error> = Box::new(ProviderError::Json(json_err));
80        assert!(e.source().is_some());
81    }
82}