Add unit tests across all model and server infrastructure layers, increasing test count from 7 to 92. Covers serde round-trips, enum methods, defaults, config parsing, error mapping, PKCE crypto (with RFC 7636 test vector), OAuth store, and SearXNG ranking/dedup logic. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
94 lines
2.7 KiB
Rust
94 lines
2.7 KiB
Rust
use axum::response::IntoResponse;
|
|
use reqwest::StatusCode;
|
|
|
|
/// Central error type for infrastructure-layer failures.
|
|
///
|
|
/// Each variant maps to an appropriate HTTP status code when converted
|
|
/// into an Axum response.
|
|
#[derive(thiserror::Error, Debug)]
|
|
pub enum Error {
|
|
#[error("{0}")]
|
|
StateError(String),
|
|
|
|
#[error("database error: {0}")]
|
|
DatabaseError(String),
|
|
|
|
#[error("configuration error: {0}")]
|
|
ConfigError(String),
|
|
|
|
#[error("IoError: {0}")]
|
|
IoError(#[from] std::io::Error),
|
|
}
|
|
|
|
impl From<mongodb::error::Error> for Error {
|
|
fn from(err: mongodb::error::Error) -> Self {
|
|
Self::DatabaseError(err.to_string())
|
|
}
|
|
}
|
|
|
|
impl IntoResponse for Error {
|
|
fn into_response(self) -> axum::response::Response {
|
|
let msg = self.to_string();
|
|
tracing::error!("Converting Error to Response: {msg}");
|
|
match self {
|
|
Self::StateError(e) | Self::ConfigError(e) => {
|
|
(StatusCode::INTERNAL_SERVER_ERROR, e).into_response()
|
|
}
|
|
Self::DatabaseError(e) => (StatusCode::SERVICE_UNAVAILABLE, e).into_response(),
|
|
Self::IoError(_) => {
|
|
(StatusCode::INTERNAL_SERVER_ERROR, "Unknown error").into_response()
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
#[cfg(test)]
|
|
mod tests {
|
|
use super::*;
|
|
use axum::response::IntoResponse;
|
|
use pretty_assertions::assert_eq;
|
|
|
|
#[test]
|
|
fn state_error_display() {
|
|
let err = Error::StateError("bad state".into());
|
|
assert_eq!(err.to_string(), "bad state");
|
|
}
|
|
|
|
#[test]
|
|
fn database_error_display() {
|
|
let err = Error::DatabaseError("connection lost".into());
|
|
assert_eq!(err.to_string(), "database error: connection lost");
|
|
}
|
|
|
|
#[test]
|
|
fn config_error_display() {
|
|
let err = Error::ConfigError("missing var".into());
|
|
assert_eq!(err.to_string(), "configuration error: missing var");
|
|
}
|
|
|
|
#[test]
|
|
fn state_error_into_response_500() {
|
|
let resp = Error::StateError("oops".into()).into_response();
|
|
assert_eq!(resp.status(), StatusCode::INTERNAL_SERVER_ERROR);
|
|
}
|
|
|
|
#[test]
|
|
fn database_error_into_response_503() {
|
|
let resp = Error::DatabaseError("down".into()).into_response();
|
|
assert_eq!(resp.status(), StatusCode::SERVICE_UNAVAILABLE);
|
|
}
|
|
|
|
#[test]
|
|
fn config_error_into_response_500() {
|
|
let resp = Error::ConfigError("bad cfg".into()).into_response();
|
|
assert_eq!(resp.status(), StatusCode::INTERNAL_SERVER_ERROR);
|
|
}
|
|
|
|
#[test]
|
|
fn io_error_into_response_500() {
|
|
let io_err = std::io::Error::new(std::io::ErrorKind::NotFound, "not found");
|
|
let resp = Error::IoError(io_err).into_response();
|
|
assert_eq!(resp.status(), StatusCode::INTERNAL_SERVER_ERROR);
|
|
}
|
|
}
|