use crate::Safe;
use anyhow::{Context, Result};
use rand::{distributions::Alphanumeric, thread_rng, Rng};
use std::{collections::HashSet, env::var, net::SocketAddr, sync::Once};
use tracing_subscriber::{fmt, EnvFilter};
const TEST_AUTH_CREDENTIALS: &str = "TEST_AUTH_CREDENTIALS";
const TEST_BOOTSTRAPPING_PEERS: &str = "TEST_BOOTSTRAPPING_PEERS";
static INIT: Once = Once::new();
fn init_logger() {
INIT.call_once(|| {
fmt()
.pretty()
.with_env_filter(EnvFilter::from_default_env())
.with_target(false)
.init()
});
}
pub async fn new_safe_instance() -> Result<Safe> {
init_logger();
let mut safe = Safe::default();
let credentials = match var(TEST_AUTH_CREDENTIALS) {
Ok(val) => {
let keypair = serde_json::from_str(&val).with_context(|| {
format!(
"Failed to parse credentials read from {} env var",
TEST_AUTH_CREDENTIALS
)
})?;
Some(keypair)
}
Err(_) => None,
};
let bootstrap_contacts = get_bootstrap_contacts()?;
safe.connect(credentials, None, Some(bootstrap_contacts))
.await?;
Ok(safe)
}
pub async fn new_read_only_safe_instance() -> Result<Safe> {
init_logger();
let mut safe = Safe::default();
let bootstrap_contacts = get_bootstrap_contacts()?;
safe.connect(None, None, Some(bootstrap_contacts)).await?;
Ok(safe)
}
pub fn random_nrs_name() -> String {
thread_rng().sample_iter(&Alphanumeric).take(15).collect()
}
fn get_bootstrap_contacts() -> Result<HashSet<SocketAddr>> {
let contacts = match var(TEST_BOOTSTRAPPING_PEERS) {
Ok(val) => serde_json::from_str(&val).with_context(|| {
format!(
"Failed to parse bootstraping contacts list from {} env var",
TEST_BOOTSTRAPPING_PEERS
)
})?,
Err(_) => {
vec!["127.0.0.1:12000".parse()?].into_iter().collect()
}
};
Ok(contacts)
}
#[macro_export]
macro_rules! retry_loop {
($async_func:expr) => {
loop {
match $async_func.await {
Ok(val) => break val,
Err(_) => tokio::time::sleep(std::time::Duration::from_millis(200)).await,
}
}
};
}
#[macro_export]
macro_rules! retry_loop_for_pattern {
($async_func:expr, $pattern:pat $(if $cond:expr)?) => {
loop {
let result = $async_func.await;
match &result {
$pattern $(if $cond)? => break result,
Ok(_) | Err(_) => tokio::time::sleep(std::time::Duration::from_millis(300)).await,
}
}
};
}