use crate::mock_server::bare_server::BareMockServer;
use crate::mock_server::pool::get_pooled_mock_server;
use crate::mock_server::MockServerBuilder;
use crate::{mock::Mock, verification::VerificationOutcome, Request};
use deadpool::managed::Object;
use log::debug;
use std::convert::Infallible;
use std::net::SocketAddr;
use std::ops::Deref;
pub struct MockServer(InnerServer);
pub(super) enum InnerServer {
Bare(BareMockServer),
Pooled(Object<BareMockServer, Infallible>),
}
impl Deref for InnerServer {
type Target = BareMockServer;
fn deref(&self) -> &Self::Target {
match self {
InnerServer::Bare(b) => b,
InnerServer::Pooled(p) => p.deref(),
}
}
}
impl MockServer {
pub(super) fn new(server: InnerServer) -> Self {
Self(server)
}
pub fn builder() -> MockServerBuilder {
MockServerBuilder::new()
}
pub async fn start() -> Self {
Self(InnerServer::Pooled(get_pooled_mock_server().await))
}
pub async fn register(&self, mock: Mock) {
self.0.register(mock).await
}
pub async fn reset(&self) {
self.0.reset().await;
}
pub async fn verify(&self) {
debug!("Verify mock expectations.");
if let VerificationOutcome::Failure(failed_verifications) = self.0.verify().await {
let received_requests_message = if let Some(received_requests) =
self.0.received_requests().await
{
if received_requests.is_empty() {
"The server did not receive any request.".into()
} else {
format!(
"Received requests:\n{}",
received_requests
.into_iter()
.enumerate()
.map(|(index, request)| {
format!(
"- Request #{}\n{}",
index + 1,
textwrap::indent(&format!("{}", request), "\t")
)
})
.collect::<String>()
)
}
} else {
"Enable request recording on the mock server to get the list of incoming requests as part of the panic message.".into()
};
let verifications_errors: String = failed_verifications
.iter()
.map(|m| format!("- {}\n", m.error_message()))
.collect();
let error_message = format!(
"Verifications failed:\n{}\n{}",
verifications_errors, received_requests_message
);
if std::thread::panicking() {
debug!("{}", &error_message);
} else {
panic!("{}", &error_message);
}
}
}
pub fn uri(&self) -> String {
self.0.uri()
}
pub fn address(&self) -> &SocketAddr {
self.0.address()
}
pub async fn received_requests(&self) -> Option<Vec<Request>> {
self.0.received_requests().await
}
}
impl Drop for MockServer {
fn drop(&mut self) {
futures::executor::block_on(self.verify())
}
}