diff --git a/orange-sdk/src/trusted_wallet/dummy.rs b/orange-sdk/src/trusted_wallet/dummy.rs index e19e8da..e223e01 100644 --- a/orange-sdk/src/trusted_wallet/dummy.rs +++ b/orange-sdk/src/trusted_wallet/dummy.rs @@ -431,7 +431,16 @@ impl TrustedWalletInterface for DummyTrustedWallet { fn stop(&self) -> Pin + Send + '_>> { Box::pin(async move { - let _ = self.ldk_node.stop(); + let ldk_node = Arc::clone(&self.ldk_node); + let (sender, receiver) = tokio::sync::oneshot::channel(); + std::thread::spawn(move || { + let _ = ldk_node.stop(); + let _ = sender.send(()); + }); + + if tokio::time::timeout(Duration::from_secs(10), receiver).await.is_err() { + eprintln!("Warning: dummy trusted LDK node stop timed out"); + } }) } } diff --git a/orange-sdk/tests/integration_tests.rs b/orange-sdk/tests/integration_tests.rs index 5a654ae..2ca01e6 100644 --- a/orange-sdk/tests/integration_tests.rs +++ b/orange-sdk/tests/integration_tests.rs @@ -9,7 +9,6 @@ use ldk_node::bitcoin::Network; use ldk_node::lightning_invoice::{Bolt11InvoiceDescription, Description}; use ldk_node::payment::{ConfirmationStatus, PaymentDirection, PaymentStatus}; use log::info; -use orange_sdk::bitcoin::hashes::Hash; use orange_sdk::{Event, PaymentInfo, PaymentType, TxStatus, WalletError}; use std::sync::Arc; use std::time::Duration; @@ -597,7 +596,7 @@ async fn test_receive_to_onchain_with_channel() { } async fn run_test_pay_lightning_from_self_custody(amountless: bool) { - test_utils::run_test(|params| async move { + test_utils::run_test(move |params| async move { let wallet = Arc::clone(¶ms.wallet); let bitcoind = Arc::clone(¶ms.bitcoind); let third_party = Arc::clone(¶ms.third_party); @@ -701,7 +700,7 @@ async fn test_pay_lightning_from_self_custody() { } async fn run_test_pay_bolt12_from_self_custody(amountless: bool) { - test_utils::run_test(|params| async move { + test_utils::run_test(move |params| async move { let wallet = Arc::clone(¶ms.wallet); let bitcoind = Arc::clone(¶ms.bitcoind); let third_party = Arc::clone(¶ms.third_party); diff --git a/orange-sdk/tests/test_utils.rs b/orange-sdk/tests/test_utils.rs index fb7de82..c9defd5 100644 --- a/orange-sdk/tests/test_utils.rs +++ b/orange-sdk/tests/test_utils.rs @@ -11,7 +11,6 @@ use corepc_node::client::bitcoin::Network; use corepc_node::{Conf, Node as Bitcoind, get_available_port}; use electrsd::ElectrsD; use electrsd::electrum_client::ElectrumApi; -use ldk_node::bitcoin::hashes::Hash; use ldk_node::lightning::ln::msgs::SocketAddress; use ldk_node::liquidity::LSPS2ServiceConfig; use ldk_node::payment::PaymentStatus; @@ -273,8 +272,22 @@ impl TestParams { #[cfg(feature = "_cashu-tests")] let _ = self._mint.stop().await; - let _ = self.lsp.stop(); - let _ = self.third_party.stop(); + tokio::join!( + stop_ldk_node("lsp", Arc::clone(&self.lsp)), + stop_ldk_node("third_party", Arc::clone(&self.third_party)), + ); + } +} + +async fn stop_ldk_node(name: &'static str, node: Arc) { + let (sender, receiver) = tokio::sync::oneshot::channel(); + std::thread::spawn(move || { + let _ = node.stop(); + let _ = sender.send(()); + }); + + if tokio::time::timeout(Duration::from_secs(10), receiver).await.is_err() { + eprintln!("Warning: {name} LDK node stop timed out"); } } @@ -283,20 +296,43 @@ impl TestParams { /// Cleanup happens automatically after the test completes. pub async fn run_test(test: F) where - F: FnOnce(TestParams) -> Fut, - Fut: Future, + F: FnOnce(TestParams) -> Fut + Send + 'static, + Fut: Future + Send + 'static, { let params = build_test_nodes().await; println!("=== test start ==="); - // Run the test and get params back - test(params.clone()).await; + let test_timeout = if std::env::var("CI").is_ok() { + Duration::from_secs(15 * 60) + } else { + Duration::from_secs(5 * 60) + }; + + let mut test_task = tokio::spawn({ + let params = params.clone(); + async move { test(params).await } + }); + let test_result = tokio::select! { + res = &mut test_task => Ok(res), + _ = tokio::time::sleep(test_timeout) => { + test_task.abort(); + let _ = test_task.await; + Err(()) + }, + }; // Always clean up - let timeout = Duration::from_secs(10); + let timeout = Duration::from_secs(30); if tokio::time::timeout(timeout, params.stop()).await.is_err() { - eprintln!("Warning: parms stop timed out after {timeout:?}"); + eprintln!("Warning: params stop timed out after {timeout:?}"); + } + + match test_result { + Ok(Ok(())) => {}, + Ok(Err(e)) if e.is_panic() => std::panic::resume_unwind(e.into_panic()), + Ok(Err(e)) => panic!("test task failed: {e}"), + Err(_) => panic!("test timed out after {test_timeout:?}"), } }