Skip to content

Commit 316bbc1

Browse files
committed
Prevent Rust test shutdown hangs
The _test-utils integration suite can stall during teardown when the LDK node in the dummy trusted wallet does not finish stopping. This keeps CI failures tied to the offending test instead of waiting for the whole job timeout.
1 parent 50ed4a8 commit 316bbc1

3 files changed

Lines changed: 41 additions & 11 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: 29 additions & 7 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;
@@ -283,20 +282,43 @@ impl TestParams {
283282
/// Cleanup happens automatically after the test completes.
284283
pub async fn run_test<F, Fut>(test: F)
285284
where
286-
F: FnOnce(TestParams) -> Fut,
287-
Fut: Future<Output = ()>,
285+
F: FnOnce(TestParams) -> Fut + Send + 'static,
286+
Fut: Future<Output = ()> + Send + 'static,
288287
{
289288
let params = build_test_nodes().await;
290289

291290
println!("=== test start ===");
292291

293-
// Run the test and get params back
294-
test(params.clone()).await;
292+
let test_timeout = if std::env::var("CI").is_ok() {
293+
Duration::from_secs(15 * 60)
294+
} else {
295+
Duration::from_secs(5 * 60)
296+
};
297+
298+
let mut test_task = tokio::spawn({
299+
let params = params.clone();
300+
async move { test(params).await }
301+
});
302+
let test_result = tokio::select! {
303+
res = &mut test_task => Ok(res),
304+
_ = tokio::time::sleep(test_timeout) => {
305+
test_task.abort();
306+
let _ = test_task.await;
307+
Err(())
308+
},
309+
};
295310

296311
// Always clean up
297-
let timeout = Duration::from_secs(10);
312+
let timeout = Duration::from_secs(30);
298313
if tokio::time::timeout(timeout, params.stop()).await.is_err() {
299-
eprintln!("Warning: parms stop timed out after {timeout:?}");
314+
eprintln!("Warning: params stop timed out after {timeout:?}");
315+
}
316+
317+
match test_result {
318+
Ok(Ok(())) => {},
319+
Ok(Err(e)) if e.is_panic() => std::panic::resume_unwind(e.into_panic()),
320+
Ok(Err(e)) => panic!("test task failed: {e}"),
321+
Err(_) => panic!("test timed out after {test_timeout:?}"),
300322
}
301323
}
302324

0 commit comments

Comments
 (0)