@@ -1943,7 +1943,7 @@ mod tests {
19431943 // Set up test nodes
19441944 let ( ( node_1, node_2) , clients) = setup_test_nodes ( ) ;
19451945
1946- // Define an activity that would make many payments (but we will shut down early)
1946+ // Define an activity that would make payments (but we will shut down early)
19471947 let activity_definition = crate :: ActivityDefinition {
19481948 source : node_1,
19491949 destination : node_2,
@@ -1997,11 +1997,88 @@ mod tests {
19971997 elapsed
19981998 ) ;
19991999
2000- // We expect fewer than the total 100 payments to be attempted
2000+ // We expect fewer than the total 10 payments to be attempted
20012001 let total_payments = simulation. get_total_payments ( ) . await ;
20022002 assert ! (
20032003 total_payments > 0 && total_payments < 10 ,
2004- "Expected between 1 and 99 payments to be attempted, got {}" ,
2004+ "Expected between 1 and 9 payments to be attempted, got {}" ,
2005+ total_payments
2006+ ) ;
2007+ }
2008+
2009+ #[ tokio:: test]
2010+ async fn test_shutdown_on_error ( ) {
2011+ // Set up test nodes with one that will produce a permanent error
2012+ let ( ( node_1, node_2) , mut clients) = setup_test_nodes ( ) ;
2013+ let mut mock_node_1 = MockLightningNode :: new ( ) ;
2014+
2015+ // Set up node 1 expectations
2016+ let node_1_clone = node_1. clone ( ) ;
2017+ mock_node_1. expect_get_info ( ) . return_const ( node_1. clone ( ) ) ;
2018+ mock_node_1
2019+ . expect_get_network ( )
2020+ . returning ( || Ok ( Network :: Regtest ) ) ;
2021+ mock_node_1
2022+ . expect_list_channels ( )
2023+ . returning ( || Ok ( vec ! [ 100_000 ] ) ) ;
2024+ mock_node_1
2025+ . expect_get_node_info ( )
2026+ . returning ( move |_| Ok ( node_1_clone. clone ( ) ) ) ;
2027+ mock_node_1. expect_track_payment ( ) . returning ( |_, _| {
2028+ Ok ( crate :: PaymentResult {
2029+ htlc_count : 1 ,
2030+ payment_outcome : crate :: PaymentOutcome :: Success ,
2031+ } )
2032+ } ) ;
2033+ mock_node_1. expect_send_payment ( ) . returning ( |_, _| {
2034+ Err ( LightningError :: PermanentError (
2035+ "Simulated permanent error" . to_string ( ) ,
2036+ ) )
2037+ } ) ;
2038+
2039+ clients. insert ( node_1. pubkey , Arc :: new ( Mutex :: new ( mock_node_1) ) ) ;
2040+
2041+ // Define an activity that attempts to send a payment from node_1 to node_2
2042+ let activity_definition = crate :: ActivityDefinition {
2043+ source : node_1,
2044+ destination : node_2,
2045+ start_secs : None , // Start immediately
2046+ count : Some ( 5 ) , // Would try multiple payments if no error occurred
2047+ interval_secs : crate :: ValueOrRange :: Value ( 1 ) , // 1 second interval
2048+ amount_msat : crate :: ValueOrRange :: Value ( 2000 ) , // 2000 msats
2049+ } ;
2050+
2051+ // Create simulation with a long timeout that we don't expect to be reached
2052+ let simulation = Simulation :: new (
2053+ SimulationCfg :: new (
2054+ Some ( 30 ) , // 30 second timeout (shouldn't matter)
2055+ 1000 , // Expected payment size
2056+ 0.1 , // Activity multiplier
2057+ None , // No result writing
2058+ Some ( 42 ) , // Seed for determinism
2059+ ) ,
2060+ clients,
2061+ vec ! [ activity_definition] ,
2062+ TaskTracker :: new ( ) ,
2063+ ) ;
2064+
2065+ // Run the simulation (should be interrupted by the error)
2066+ let start = std:: time:: Instant :: now ( ) ;
2067+ let _ = simulation. run ( ) . await ;
2068+ let elapsed = start. elapsed ( ) ;
2069+
2070+ // Check that simulation ran for a short time (less than our expected 5 seconds)
2071+ assert ! (
2072+ elapsed < Duration :: from_secs( 5 ) ,
2073+ "Simulation should have shut down quickly after encountering the error, took {:?}" ,
2074+ elapsed
2075+ ) ;
2076+
2077+ // We expect no successful payments to be recorded
2078+ let total_payments = simulation. get_total_payments ( ) . await ;
2079+ assert_eq ! (
2080+ total_payments, 0 ,
2081+ "Expected no payments to be recorded, got {}" ,
20052082 total_payments
20062083 ) ;
20072084 }
0 commit comments