use {
crate::Envelope,
std::{
fmt,
result,
sync::PoisonError,
},
};
pub type Result<T> = result::Result<T, Error>;
#[derive(Debug)]
pub enum Error {
InvalidAddress,
WrongStrategy,
QueueFull(Envelope),
LockFailed(String),
ServiceNotFound,
ProcessorNotFound,
}
impl<T> From<PoisonError<T>> for Error {
fn from(e: PoisonError<T>) -> Self { Self::LockFailed(format!("Lock Poisoned: {e}")) }
}
impl fmt::Display for Error {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
match self {
Self::InvalidAddress => f.write_str("Invalid address."),
Self::WrongStrategy => f.write_str("Wrong balancing strategy."),
Self::QueueFull(msg) => write!(f, "Queue is full: {:?}", msg),
Self::LockFailed(e) => write!(f, "Failed to acquire enqueue lock: {}", e),
Self::ServiceNotFound => f.write_str("Service not found."),
Self::ProcessorNotFound => f.write_str("Processor not found."),
}
}
}
#[cfg(test)]
mod tests {
use {
super::*,
crate::{
Address,
message::Payload,
},
std::{
sync::{
Arc,
Mutex,
},
thread::spawn,
},
};
#[test]
fn error_display() {
let invalid_addr = Error::InvalidAddress;
let wrong_strategy = Error::WrongStrategy;
let lock_failed = Error::LockFailed("test".to_string());
let service_not_found = Error::ServiceNotFound;
let processor_not_found = Error::ProcessorNotFound;
assert_eq!(invalid_addr.to_string(), "Invalid address.");
assert_eq!(
wrong_strategy.to_string(),
"Wrong balancing strategy."
);
assert_eq!(
lock_failed.to_string(),
"Failed to acquire enqueue lock: test"
);
assert_eq!(
service_not_found.to_string(),
"Service not found."
);
assert_eq!(
processor_not_found.to_string(),
"Processor not found."
);
}
#[test]
fn poison_error() {
let data = Arc::new(Mutex::new(0));
let data_dup = data.clone();
let _ = spawn(move || {
let _lock = data_dup.lock().unwrap();
panic!("poisoned")
})
.join();
let err: Error = data
.lock()
.unwrap_err()
.into();
assert!(matches!(err, Error::LockFailed(_)))
}
#[test]
fn queue_full_error() -> Result<()> {
let src = Address::parse("http://source.com")?;
let dst = Address::parse("http://destination.com")?;
let payload = Payload::default();
let msg = Envelope::new(src.clone(), dst.clone(), payload.clone());
let queue_full = Error::QueueFull(msg);
assert!(matches!(queue_full, Error::QueueFull(_)));
assert_eq!(
queue_full.to_string(),
format!(
"Queue is full: {:?}",
Envelope::new(src, dst, payload)
)
);
Ok(())
}
}