use crate::{
Error, Result,
client::Client,
commands::{ConnectionCommands, DebugCommands},
sleep,
tests::get_test_client,
};
use serial_test::serial;
use std::{future::Future, time::Duration};
type Verdict = std::result::Result<(), String>;
#[tokio::test]
#[serial]
async fn standalone_server_panic() -> Result<()> {
with_server_restart("DEBUG PANIC", async |client| {
if client.debug_panic().await.is_ok() {
return Err("the server acknowledged instead of dying".to_owned());
}
if client.ping::<()>(()).await.is_ok() {
return Err("the dead server answered a ping".to_owned());
}
Ok(())
})
.await
}
#[tokio::test]
#[serial]
async fn standalone_server_oom() -> Result<()> {
with_server_restart("DEBUG OOM", async |client| {
check_died(client.debug_oom().await)
})
.await
}
#[tokio::test]
#[serial]
async fn standalone_server_assert() -> Result<()> {
with_server_restart("DEBUG ASSERT", async |client| {
check_died(client.debug_assert().await)
})
.await
}
#[tokio::test]
#[serial]
async fn standalone_server_restart() -> Result<()> {
with_server_restart("DEBUG RESTART", async |client| {
check_died(client.debug_restart(None).await)
})
.await?;
with_server_restart("DEBUG RESTART 100", async |client| {
check_died(client.debug_restart(Some(Duration::from_millis(100))).await)
})
.await
}
#[tokio::test]
#[serial]
async fn standalone_server_crash_and_recover() -> Result<()> {
with_server_restart("DEBUG CRASH-AND-RECOVER", async |client| {
check_died(client.debug_crash_and_recover(None).await)
})
.await?;
with_server_restart("DEBUG CRASH-AND-RECOVER 100", async |client| {
check_died(
client
.debug_crash_and_recover(Some(Duration::from_millis(100)))
.await,
)
})
.await
}
fn check_died(result: Result<()>) -> Verdict {
match result {
Err(Error::Redis(e)) => Err(format!("the server answered instead of dying: {e}")),
Err(_) => Ok(()),
Ok(()) => Err("the server acknowledged instead of dying".to_owned()),
}
}
async fn with_server_restart<F, Fut>(what: &str, body: F) -> Result<()>
where
F: FnOnce(Client) -> Fut,
Fut: Future<Output = Verdict>,
{
let client = get_test_client().await?;
let outcome = body(client).await;
wait_for_standalone_server_restart(what).await;
match outcome {
Ok(()) => Ok(()),
Err(message) => panic!("{message}"),
}
}
async fn wait_for_standalone_server_restart(what: &str) {
for _ in 0..100 {
sleep(Duration::from_millis(200)).await;
let Ok(client) = get_test_client().await else {
continue;
};
if client.ping::<()>(()).await.is_ok() {
return;
}
}
panic!("the test server did not come back up after {what}");
}