Skip to content

Commit 1a62c46

Browse files
authored
Merge pull request #60 from lightningdevkit/fix-ci-hang
Prevent Rust test shutdown hangs
2 parents 50ed4a8 + 0d3fd1f commit 1a62c46

3 files changed

Lines changed: 57 additions & 13 deletions

File tree

orange-sdk/src/trusted_wallet/dummy.rs

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -431,7 +431,16 @@ impl TrustedWalletInterface for DummyTrustedWallet {
431431

432432
fn stop(&self) -> Pin<Box<dyn Future<Output = ()> + Send + '_>> {
433433
Box::pin(async move {
434-
let _ = self.ldk_node.stop();
434+
let ldk_node = Arc::clone(&self.ldk_node);
435+
let (sender, receiver) = tokio::sync::oneshot::channel();
436+
std::thread::spawn(move || {
437+
let _ = ldk_node.stop();
438+
let _ = sender.send(());
439+
});
440+
441+
if tokio::time::timeout(Duration::from_secs(10), receiver).await.is_err() {
442+
eprintln!("Warning: dummy trusted LDK node stop timed out");
443+
}
435444
})
436445
}
437446
}

orange-sdk/tests/integration_tests.rs

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,6 @@ use ldk_node::bitcoin::Network;
99
use ldk_node::lightning_invoice::{Bolt11InvoiceDescription, Description};
1010
use ldk_node::payment::{ConfirmationStatus, PaymentDirection, PaymentStatus};
1111
use log::info;
12-
use orange_sdk::bitcoin::hashes::Hash;
1312
use orange_sdk::{Event, PaymentInfo, PaymentType, TxStatus, WalletError};
1413
use std::sync::Arc;
1514
use std::time::Duration;
@@ -597,7 +596,7 @@ async fn test_receive_to_onchain_with_channel() {
597596
}
598597

599598
async fn run_test_pay_lightning_from_self_custody(amountless: bool) {
600-
test_utils::run_test(|params| async move {
599+
test_utils::run_test(move |params| async move {
601600
let wallet = Arc::clone(&params.wallet);
602601
let bitcoind = Arc::clone(&params.bitcoind);
603602
let third_party = Arc::clone(&params.third_party);
@@ -701,7 +700,7 @@ async fn test_pay_lightning_from_self_custody() {
701700
}
702701

703702
async fn run_test_pay_bolt12_from_self_custody(amountless: bool) {
704-
test_utils::run_test(|params| async move {
703+
test_utils::run_test(move |params| async move {
705704
let wallet = Arc::clone(&params.wallet);
706705
let bitcoind = Arc::clone(&params.bitcoind);
707706
let third_party = Arc::clone(&params.third_party);

orange-sdk/tests/test_utils.rs

Lines changed: 45 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,6 @@ use corepc_node::client::bitcoin::Network;
1111
use corepc_node::{Conf, Node as Bitcoind, get_available_port};
1212
use electrsd::ElectrsD;
1313
use electrsd::electrum_client::ElectrumApi;
14-
use ldk_node::bitcoin::hashes::Hash;
1514
use ldk_node::lightning::ln::msgs::SocketAddress;
1615
use ldk_node::liquidity::LSPS2ServiceConfig;
1716
use ldk_node::payment::PaymentStatus;
@@ -273,8 +272,22 @@ impl TestParams {
273272
#[cfg(feature = "_cashu-tests")]
274273
let _ = self._mint.stop().await;
275274

276-
let _ = self.lsp.stop();
277-
let _ = self.third_party.stop();
275+
tokio::join!(
276+
stop_ldk_node("lsp", Arc::clone(&self.lsp)),
277+
stop_ldk_node("third_party", Arc::clone(&self.third_party)),
278+
);
279+
}
280+
}
281+
282+
async fn stop_ldk_node(name: &'static str, node: Arc<Node>) {
283+
let (sender, receiver) = tokio::sync::oneshot::channel();
284+
std::thread::spawn(move || {
285+
let _ = node.stop();
286+
let _ = sender.send(());
287+
});
288+
289+
if tokio::time::timeout(Duration::from_secs(10), receiver).await.is_err() {
290+
eprintln!("Warning: {name} LDK node stop timed out");
278291
}
279292
}
280293

@@ -283,20 +296,43 @@ impl TestParams {
283296
/// Cleanup happens automatically after the test completes.
284297
pub async fn run_test<F, Fut>(test: F)
285298
where
286-
F: FnOnce(TestParams) -> Fut,
287-
Fut: Future<Output = ()>,
299+
F: FnOnce(TestParams) -> Fut + Send + 'static,
300+
Fut: Future<Output = ()> + Send + 'static,
288301
{
289302
let params = build_test_nodes().await;
290303

291304
println!("=== test start ===");
292305

293-
// Run the test and get params back
294-
test(params.clone()).await;
306+
let test_timeout = if std::env::var("CI").is_ok() {
307+
Duration::from_secs(15 * 60)
308+
} else {
309+
Duration::from_secs(5 * 60)
310+
};
311+
312+
let mut test_task = tokio::spawn({
313+
let params = params.clone();
314+
async move { test(params).await }
315+
});
316+
let test_result = tokio::select! {
317+
res = &mut test_task => Ok(res),
318+
_ = tokio::time::sleep(test_timeout) => {
319+
test_task.abort();
320+
let _ = test_task.await;
321+
Err(())
322+
},
323+
};
295324

296325
// Always clean up
297-
let timeout = Duration::from_secs(10);
326+
let timeout = Duration::from_secs(30);
298327
if tokio::time::timeout(timeout, params.stop()).await.is_err() {
299-
eprintln!("Warning: parms stop timed out after {timeout:?}");
328+
eprintln!("Warning: params stop timed out after {timeout:?}");
329+
}
330+
331+
match test_result {
332+
Ok(Ok(())) => {},
333+
Ok(Err(e)) if e.is_panic() => std::panic::resume_unwind(e.into_panic()),
334+
Ok(Err(e)) => panic!("test task failed: {e}"),
335+
Err(_) => panic!("test timed out after {test_timeout:?}"),
300336
}
301337
}
302338

0 commit comments

Comments
 (0)