use lazy_static::lazy_static; use tokio::sync::Mutex; use serai_client::Serai; pub mod tx; pub mod validator_sets; pub mod in_instructions; pub const URL: &str = "ws://127.0.0.1:9944"; pub async fn serai() -> Serai { Serai::new(URL).await.unwrap() } lazy_static! { pub static ref SEQUENTIAL: Mutex<()> = Mutex::new(()); } #[macro_export] macro_rules! serai_test { ($(async fn $name: ident() $body: block)*) => { $( #[tokio::test] async fn $name() { use std::process::Command; let guard = common::SEQUENTIAL.lock().await; let is_running = || { !( if let Ok(res) = Command::new("pidof").arg("serai-node").output() { res } else { Command::new("pgrep") .arg("serai-node") .output() .expect("neither pidof nor pgrep were available") } ).stdout.is_empty() }; // Spawn a fresh Serai node let mut command = { use core::time::Duration; use std::path::Path; // Make sure a node isn't already running assert!(!is_running()); let node = { let this_crate = Path::new(env!("CARGO_MANIFEST_DIR")); let top_level = this_crate.join("../../"); top_level.join("target/debug/serai-node") }; let command = Command::new(node).arg("--dev").spawn().unwrap(); while Serai::new(common::URL).await.is_err() { tokio::time::sleep(Duration::from_secs(1)).await; } let serai = serai().await; while serai.get_latest_block_hash().await.is_err() { tokio::time::sleep(Duration::from_secs(1)).await; } // TODO: https://github.com/serai-dex/serai/247 if std::env::var("GITHUB_CI") == Ok("true".to_string()) { tokio::time::sleep(Duration::from_secs(60)).await; } // Sanity check the pidof command is well-formed assert!(is_running()); command }; let local = tokio::task::LocalSet::new(); local.run_until(async move { if let Err(err) = tokio::task::spawn_local(async move { $body }).await { drop(guard); let _ = command.kill(); Err(err).unwrap() } else { command.kill().unwrap(); } assert!(!is_running()); }).await; } )* } }