@@ -1864,4 +1864,72 @@ mod tests {
18641864 total_payments
18651865 ) ;
18661866 }
1867+
1868+ #[ tokio:: test]
1869+ async fn test_manual_shutdown ( ) {
1870+ // Set up test nodes
1871+ let ( ( node_1, node_2) , clients) = setup_test_nodes ( ) ;
1872+
1873+ // Define an activity that would make many payments (but we will shut down early)
1874+ let activity_definition = crate :: ActivityDefinition {
1875+ source : node_1,
1876+ destination : node_2,
1877+ start_secs : None ,
1878+ count : Some ( 10 ) ,
1879+ interval_secs : crate :: ValueOrRange :: Value ( 1 ) ,
1880+ amount_msat : crate :: ValueOrRange :: Value ( 2000 ) ,
1881+ } ;
1882+
1883+ // Create simulation with no timeout
1884+ let simulation = Simulation :: new (
1885+ SimulationCfg :: new (
1886+ None , // No timeout
1887+ 1000 , // Expected payment size
1888+ 0.1 , // Activity multiplier
1889+ None , // No result writing
1890+ Some ( 42 ) , // Seed for determinism
1891+ ) ,
1892+ clients,
1893+ vec ! [ activity_definition] , // Use defined activity with many payments
1894+ TaskTracker :: new ( ) ,
1895+ ) ;
1896+
1897+ // Create a cloned reference for the shutdown task
1898+ let sim_clone = simulation. clone ( ) ;
1899+
1900+ // Start a task that will manually shut down the simulation after a short delay
1901+ tokio:: spawn ( async move {
1902+ // Wait a little bit to allow some payments to complete
1903+ tokio:: time:: sleep ( Duration :: from_secs ( 3 ) ) . await ;
1904+
1905+ // Manually trigger shutdown
1906+ log:: info!( "Manually triggering simulation shutdown" ) ;
1907+ sim_clone. shutdown ( ) ;
1908+ } ) ;
1909+
1910+ // Run the simulation (should be interrupted by our manual shutdown)
1911+ let start = std:: time:: Instant :: now ( ) ;
1912+ let result = simulation. run ( ) . await ;
1913+ let elapsed = start. elapsed ( ) ;
1914+
1915+ // Verify the simulation shut down correctly
1916+ assert ! ( result. is_ok( ) , "Simulation should end without error" ) ;
1917+
1918+ // Check that simulation ran for approximately the time until manual shutdown (with some margin)
1919+ let expected_runtime = Duration :: from_secs ( 3 ) ;
1920+ let margin = Duration :: from_secs ( 1 ) ;
1921+ assert ! (
1922+ elapsed >= expected_runtime && elapsed <= expected_runtime + margin,
1923+ "Simulation should have run for approximately 3 seconds, but took {:?}" ,
1924+ elapsed
1925+ ) ;
1926+
1927+ // We expect fewer than the total 100 payments to be attempted
1928+ let total_payments = simulation. get_total_payments ( ) . await ;
1929+ assert ! (
1930+ total_payments > 0 && total_payments < 10 ,
1931+ "Expected between 1 and 99 payments to be attempted, got {}" ,
1932+ total_payments
1933+ ) ;
1934+ }
18671935}
0 commit comments