#![allow(dead_code)]
use std::env;
use std::future::Future;
use std::time::Duration;
use soothe_client::is_daemon_live;
use soothe_client::session::connect_with_retries;
use soothe_client::Client;
use tempfile::TempDir;
pub const TEST_DEADLINE: Duration = Duration::from_secs(180);
pub fn daemon_url() -> String {
env::var("SOOTHE_WS_URL")
.or_else(|_| env::var("SOOTHE_DAEMON_URL"))
.unwrap_or_else(|_| "ws://127.0.0.1:8765".into())
}
pub fn integration_flag() -> Option<bool> {
match env::var("SOOTHE_INTEGRATION") {
Ok(v) => {
let v = v.to_ascii_lowercase();
if matches!(v.as_str(), "0" | "false" | "no") {
Some(false)
} else if matches!(v.as_str(), "1" | "true" | "yes") {
Some(true)
} else {
None
}
}
Err(_) => None,
}
}
pub async fn skip_if_no_daemon_inner(url: String) -> Option<String> {
if integration_flag() == Some(false) {
eprintln!("skip: SOOTHE_INTEGRATION disabled");
return None;
}
let probe =
async { is_daemon_live(&url, Duration::from_secs(3), true, Duration::from_secs(5)).await };
let live = tokio::time::timeout(Duration::from_secs(10), probe)
.await
.unwrap_or(false);
if integration_flag() != Some(true) && !live {
eprintln!("skip: daemon not live at {url}");
return None;
}
if integration_flag() == Some(true) {
assert!(live, "daemon not live at {url}");
}
Some(url)
}
pub async fn connect_ready(url: &str) -> Client {
let client = Client::new(url);
tokio::time::timeout(Duration::from_secs(20), async {
connect_with_retries(&client, 8, Duration::from_millis(150)).await
})
.await
.expect("connect timed out")
.expect("connect");
let _ = tokio::time::timeout(
Duration::from_secs(10),
client.wait_for_daemon_ready(Duration::from_secs(10)),
)
.await;
assert!(
client.is_connected() && client.is_handshake_complete(),
"expected connected + handshake complete"
);
client
}
pub async fn with_deadline<F, T>(fut: F) -> T
where
F: Future<Output = T>,
{
match tokio::time::timeout(TEST_DEADLINE, fut).await {
Ok(v) => v,
Err(_) => panic!("integration test exceeded {:?}", TEST_DEADLINE),
}
}
pub fn temp_workspace() -> TempDir {
tempfile::tempdir().expect("tempdir")
}
pub fn loop_id_from(resp: &serde_json::Map<String, serde_json::Value>) -> Option<String> {
resp.get("loop_id")
.or_else(|| resp.get("id"))
.and_then(|v| v.as_str())
.filter(|s| !s.is_empty())
.map(|s| s.to_string())
}
pub fn job_id_from(resp: &serde_json::Map<String, serde_json::Value>) -> Option<String> {
resp.get("job_id")
.or_else(|| resp.get("id"))
.and_then(|v| v.as_str())
.filter(|s| !s.is_empty())
.map(|s| s.to_string())
}