Skip to main content

mbr_server/
errors.rs

1//! Errors owned by the HTTP server.
2//!
3//! Everything else the server can fail with is a core error
4//! ([`mbr_core::errors`]); only what needs the server's own types lives here.
5
6use mbr_core::errors::{MbrError, TemplateError};
7use thiserror::Error;
8
9/// Errors related to the HTTP server.
10#[derive(Debug, Error)]
11pub enum ServerError {
12    #[error("Failed to bind to {addr}")]
13    BindFailed {
14        addr: String,
15        #[source]
16        source: std::io::Error,
17    },
18
19    #[error("Server failed to start")]
20    StartFailed(#[source] std::io::Error),
21
22    #[error("Failed to get local address")]
23    LocalAddrFailed(#[source] std::io::Error),
24
25    #[error("Template initialization failed: {0}")]
26    TemplateInit(#[from] TemplateError),
27
28    #[error("Tracing initialization failed")]
29    TracingInit,
30}
31
32/// Lets `?` lift a [`ServerError`] into [`MbrError::Server`], as the derived
33/// `#[from]` did when both enums lived in one crate.
34impl From<ServerError> for MbrError {
35    fn from(err: ServerError) -> Self {
36        MbrError::Server(Box::new(err))
37    }
38}
39
40#[cfg(test)]
41mod tests {
42    use super::*;
43    use std::io::{Error as IoError, ErrorKind};
44
45    #[test]
46    fn test_server_error_display() {
47        let err = ServerError::BindFailed {
48            addr: "127.0.0.1:8080".to_string(),
49            source: IoError::new(ErrorKind::AddrInUse, "address in use"),
50        };
51        assert!(err.to_string().contains("127.0.0.1:8080"));
52        assert!(err.to_string().contains("Failed to bind"));
53    }
54
55    #[test]
56    fn test_server_error_to_mbr_error() {
57        let server_err = ServerError::TracingInit;
58        let mbr_err: MbrError = server_err.into();
59
60        match &mbr_err {
61            MbrError::Server(inner) => assert!(matches!(
62                inner.downcast_ref::<ServerError>(),
63                Some(ServerError::TracingInit)
64            )),
65            _ => panic!("Expected MbrError::Server(TracingInit), got {:?}", mbr_err),
66        }
67    }
68
69    /// The message is the one the single-crate `#[from]` variant printed:
70    /// `MbrError`'s prefix plus the inner error's own Display.
71    #[test]
72    fn test_server_error_message_through_mbr_error() {
73        let mbr_err: MbrError = ServerError::TracingInit.into();
74        assert_eq!(
75            mbr_err.to_string(),
76            "Server error: Tracing initialization failed"
77        );
78    }
79}