diff --git a/crates/pop-cli/tests/chain.rs b/crates/pop-cli/tests/chain.rs index 9eab10aa7..4523c3397 100644 --- a/crates/pop-cli/tests/chain.rs +++ b/crates/pop-cli/tests/chain.rs @@ -39,8 +39,8 @@ impl Drop for TestChildProcess { const RPC_CONNECT_TIMEOUT_SECS: u64 = 5; const RPC_REQUEST_TIMEOUT_SECS: u64 = 5; -const COMMAND_TIMEOUT_SECS: u64 = 120; -const BLOCK_PRODUCTION_TIMEOUT_SECS: u64 = 60; +const COMMAND_WAIT_TIMEOUT_SECS: u64 = 600; +const CALL_COMMAND_TIMEOUT_SECS: u64 = 120; async fn wait_for_command_success( command: &mut tokio::process::Command, @@ -64,6 +64,24 @@ async fn wait_for_command_success( Ok(()) } +async fn terminate_child_process(child: &mut Child) -> Result<()> { + if child.try_wait()?.is_some() { + return Ok(()); + } + + #[cfg(unix)] + if let Some(pid) = child.id() { + let _ = std::process::Command::new("kill").args(["-INT", &pid.to_string()]).status(); + if let Ok(Ok(_)) = tokio::time::timeout(Duration::from_secs(20), child.wait()).await { + return Ok(()); + } + } + + let _ = child.kill().await; + let _ = child.wait().await; + Ok(()) +} + async fn rpc_request_string(url: &str, method: &str) -> Option { let client = tokio::time::timeout( Duration::from_secs(RPC_CONNECT_TIMEOUT_SECS), @@ -122,46 +140,6 @@ async fn wait_for_rpc_ready( } /// Wait until finalized head changes, proving blocks/finality are progressing. -async fn wait_for_block_production( - url: &str, - timeout_secs: u64, - process: &mut TestChildProcess, -) -> Result<()> { - let timeout = Duration::from_secs(timeout_secs); - let start = std::time::Instant::now(); - let mut last_head = None; - - println!("Waiting for block production at {} (timeout: {}s)...", url, timeout_secs); - - loop { - if start.elapsed() > timeout { - return Err(anyhow::anyhow!( - "Finalized head did not advance at {} within {:?}", - url, - timeout - )); - } - - if let Some(status) = process.0.try_wait()? { - return Err(anyhow::anyhow!( - "Network process exited before block production was observed: {status}" - )); - } - - if let Some(head) = rpc_request_string(url, "chain_getFinalizedHead").await { - if let Some(previous) = &last_head && - previous != &head - { - println!("✓ Finalized head advanced (took {:?})", start.elapsed()); - return Ok(()); - } - last_head = Some(head); - } - - tokio::time::sleep(Duration::from_secs(2)).await; - } -} - fn write_network_config( network_toml_path: &Path, chain_spec_path: &Path, @@ -224,19 +202,12 @@ async fn spawn_network_with_retry( match wait_for_rpc_ready(&localhost_url, timeout, &mut process).await { Ok(_) => { - wait_for_block_production( - &localhost_url, - BLOCK_PRODUCTION_TIMEOUT_SECS, - &mut process, - ) - .await?; println!("✓ Network started successfully on attempt {}", attempt); return Ok((process, localhost_url)); }, Err(e) => { println!("✗ Attempt {} failed: {}", attempt, e); - let _ = process.0.kill().await; - let _ = process.0.wait().await; + let _ = terminate_child_process(&mut process.0).await; if attempt < max_retries { println!("Waiting 5s before retry..."); @@ -277,7 +248,12 @@ async fn generate_all_the_templates() -> Result<()> { "--verify", ], ); - assert!(command.spawn()?.wait().await?.success()); + wait_for_command_success( + &mut command, + COMMAND_WAIT_TIMEOUT_SECS, + "pop new chain