From 7a6a958179830734f1835ee1f8ee989bb5c465c9 Mon Sep 17 00:00:00 2001 From: Oleksandr Pravdyvyi Date: Thu, 31 Jul 2025 14:40:23 +0300 Subject: [PATCH] fix: integration tests added --- Cargo.lock | 1 + ci_scripts/test-ubuntu.sh | 4 +- integration_tests/Cargo.toml | 1 + integration_tests/src/lib.rs | 297 +++++++++++++++--- .../src/sequencer_store/accounts_store.rs | 6 +- 5 files changed, 266 insertions(+), 43 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index de96e5fd..99b6f97f 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -2399,6 +2399,7 @@ dependencies = [ "sequencer_runner", "serde", "serde_json", + "tempfile", "tokio", "toml 0.7.8", ] diff --git a/ci_scripts/test-ubuntu.sh b/ci_scripts/test-ubuntu.sh index 745a3321..47d79fae 100644 --- a/ci_scripts/test-ubuntu.sh +++ b/ci_scripts/test-ubuntu.sh @@ -4,4 +4,6 @@ curl -L https://risczero.com/install | bash /home/runner/.risc0/bin/rzup install source env.sh -cargo test --release \ No newline at end of file +cargo test --release +cd integration_tests +cargo run $(pwd)/configs/debug all \ No newline at end of file diff --git a/integration_tests/Cargo.toml b/integration_tests/Cargo.toml index 9558b9f1..0e964905 100644 --- a/integration_tests/Cargo.toml +++ b/integration_tests/Cargo.toml @@ -15,6 +15,7 @@ actix-web.workspace = true tokio.workspace = true toml.workspace = true hex.workspace = true +tempfile.workspace = true [dependencies.clap] features = ["derive", "env"] diff --git a/integration_tests/src/lib.rs b/integration_tests/src/lib.rs index 375a5234..d707be73 100644 --- a/integration_tests/src/lib.rs +++ b/integration_tests/src/lib.rs @@ -1,11 +1,13 @@ use std::{path::PathBuf, sync::Arc, time::Duration}; +use actix_web::dev::ServerHandle; use anyhow::Result; use clap::Parser; use common::rpc_primitives::RpcConfig; use log::info; -use node_core::NodeCore; -use sequencer_core::SequencerCore; +use node_core::{NodeCore, config::NodeConfig}; +use sequencer_core::{SequencerCore, config::SequencerConfig}; +use tempfile::TempDir; use tokio::{sync::Mutex, task::JoinHandle}; #[derive(Parser, Debug)] @@ -13,26 +15,38 @@ use tokio::{sync::Mutex, task::JoinHandle}; struct Args { /// Path to configs home_dir: PathBuf, + /// Test name + test_name: String, } pub const ACC_SENDER: &str = "0d96dfcc414019380c9dde0cd3dce5aac90fb5443bf871108741aeafde552ad7"; pub const ACC_RECEIVER: &str = "974870e9be8d0ac08aa83b3fc7a7a686291d8732508aba98b36080f39c2cf364"; -pub async fn main_tests_runner() -> Result<()> { - env_logger::init(); - - let args = Args::parse(); - let Args { home_dir } = args; +pub const TIME_TO_WAIT_FOR_BLOCK_SECONDS: u64 = 12; +#[allow(clippy::type_complexity)] +pub async fn pre_test( + home_dir: PathBuf, +) -> Result<( + ServerHandle, + JoinHandle>, + ServerHandle, + TempDir, + TempDir, + Arc>, +)> { let home_dir_sequencer = home_dir.join("sequencer"); let home_dir_node = home_dir.join("node"); - let sequencer_config = + let mut sequencer_config = sequencer_runner::config::from_file(home_dir_sequencer.join("sequencer_config.json")) .unwrap(); - let node_config = + let mut node_config = node_runner::config::from_file(home_dir_node.join("node_config.json")).unwrap(); + let (temp_dir_node, temp_dir_sequencer) = + replace_home_dir_with_temp_dir_in_configs(&mut node_config, &mut sequencer_config); + let block_timeout = sequencer_config.block_create_timeout_millis; let sequencer_port = sequencer_config.port; @@ -73,6 +87,7 @@ pub async fn main_tests_runner() -> Result<()> { let node_port = node_config.port; let node_core = NodeCore::start_from_config_update_chain(node_config.clone()).await?; + let wrapped_node_core = Arc::new(Mutex::new(node_core)); let http_server = node_rpc::new_http_server( @@ -84,42 +99,42 @@ pub async fn main_tests_runner() -> Result<()> { let node_http_server_handle = http_server.handle(); tokio::spawn(http_server); - info!("Waiting for first block creation"); - tokio::time::sleep(Duration::from_secs(12)).await; + Ok(( + seq_http_server_handle, + sequencer_loop_handle, + node_http_server_handle, + temp_dir_node, + temp_dir_sequencer, + wrapped_node_core, + )) +} - let acc_sender = hex::decode(ACC_SENDER).unwrap().try_into().unwrap(); - let acc_receiver = hex::decode(ACC_RECEIVER).unwrap().try_into().unwrap(); +pub fn replace_home_dir_with_temp_dir_in_configs( + node_config: &mut NodeConfig, + sequencer_config: &mut SequencerConfig, +) -> (TempDir, TempDir) { + let temp_dir_node = tempfile::tempdir().unwrap(); + let temp_dir_sequencer = tempfile::tempdir().unwrap(); - { - let guard = wrapped_node_core.lock().await; + node_config.home = temp_dir_node.path().to_path_buf(); + sequencer_config.home = temp_dir_sequencer.path().to_path_buf(); - let res = guard - .send_public_native_token_transfer(acc_sender, acc_receiver, 100) - .await - .unwrap(); + (temp_dir_node, temp_dir_sequencer) +} - info!("Res of tx_send is {res:#?}"); - - info!("Waiting for next block creation"); - tokio::time::sleep(Duration::from_secs(12)).await; - - info!("Checking correct balance move"); - let acc_1_balance = guard - .sequencer_client - .get_account_balance(ACC_SENDER.to_string()) - .await - .unwrap(); - let acc_2_balance = guard - .sequencer_client - .get_account_balance(ACC_RECEIVER.to_string()) - .await - .unwrap(); - - info!("Balance of sender : {acc_1_balance:#?}"); - info!("Balance of receiver : {acc_2_balance:#?}"); - } - - info!("Success!"); +#[allow(clippy::type_complexity)] +pub async fn post_test( + residual: ( + ServerHandle, + JoinHandle>, + ServerHandle, + TempDir, + TempDir, + Arc>, + ), +) { + let (seq_http_server_handle, sequencer_loop_handle, node_http_server_handle, _, _, _) = + residual; info!("Cleanup"); @@ -127,5 +142,205 @@ pub async fn main_tests_runner() -> Result<()> { sequencer_loop_handle.abort(); seq_http_server_handle.stop(true).await; + //At this point all of the references to node_core and sequencer_core must be lost. + //So they are dropped and tempdirs will be dropped too, +} + +pub async fn test_success(wrapped_node_core: Arc>) { + let acc_sender = hex::decode(ACC_SENDER).unwrap().try_into().unwrap(); + let acc_receiver = hex::decode(ACC_RECEIVER).unwrap().try_into().unwrap(); + + let guard = wrapped_node_core.lock().await; + + let _res = guard + .send_public_native_token_transfer(acc_sender, acc_receiver, 100) + .await + .unwrap(); + + info!("Waiting for next block creation"); + tokio::time::sleep(Duration::from_secs(TIME_TO_WAIT_FOR_BLOCK_SECONDS)).await; + + info!("Checking correct balance move"); + let acc_1_balance = guard + .sequencer_client + .get_account_balance(ACC_SENDER.to_string()) + .await + .unwrap(); + let acc_2_balance = guard + .sequencer_client + .get_account_balance(ACC_RECEIVER.to_string()) + .await + .unwrap(); + + info!("Balance of sender : {acc_1_balance:#?}"); + info!("Balance of receiver : {acc_2_balance:#?}"); + + assert_eq!(acc_1_balance.balance, 9900); + assert_eq!(acc_2_balance.balance, 20100); + + info!("Success!"); +} + +pub async fn test_success_move_to_another_account(wrapped_node_core: Arc>) { + let acc_sender = hex::decode(ACC_SENDER).unwrap().try_into().unwrap(); + let acc_receiver_new_acc = [42; 32]; + + let hex_acc_reveiver_new_acc = hex::encode(acc_receiver_new_acc); + + let guard = wrapped_node_core.lock().await; + + let _res = guard + .send_public_native_token_transfer(acc_sender, acc_receiver_new_acc, 100) + .await + .unwrap(); + + info!("Waiting for next block creation"); + tokio::time::sleep(Duration::from_secs(TIME_TO_WAIT_FOR_BLOCK_SECONDS)).await; + + info!("Checking correct balance move"); + let acc_1_balance = guard + .sequencer_client + .get_account_balance(ACC_SENDER.to_string()) + .await + .unwrap(); + let acc_2_balance = guard + .sequencer_client + .get_account_balance(hex_acc_reveiver_new_acc) + .await + .unwrap(); + + info!("Balance of sender : {acc_1_balance:#?}"); + info!("Balance of receiver : {acc_2_balance:#?}"); + + assert_eq!(acc_1_balance.balance, 9900); + assert_eq!(acc_2_balance.balance, 100); + + info!("Success!"); +} + +pub async fn test_failure(wrapped_node_core: Arc>) { + let acc_sender = hex::decode(ACC_SENDER).unwrap().try_into().unwrap(); + let acc_receiver = hex::decode(ACC_RECEIVER).unwrap().try_into().unwrap(); + + let guard = wrapped_node_core.lock().await; + + let _res = guard + .send_public_native_token_transfer(acc_sender, acc_receiver, 100000) + .await + .unwrap(); + + info!("Waiting for next block creation"); + tokio::time::sleep(Duration::from_secs(TIME_TO_WAIT_FOR_BLOCK_SECONDS)).await; + + info!("Checking correct balance move"); + let acc_1_balance = guard + .sequencer_client + .get_account_balance(ACC_SENDER.to_string()) + .await + .unwrap(); + let acc_2_balance = guard + .sequencer_client + .get_account_balance(ACC_RECEIVER.to_string()) + .await + .unwrap(); + + info!("Balance of sender : {acc_1_balance:#?}"); + info!("Balance of receiver : {acc_2_balance:#?}"); + + assert_eq!(acc_1_balance.balance, 10000); + assert_eq!(acc_2_balance.balance, 20000); + + info!("Success!"); +} + +pub async fn main_tests_runner() -> Result<()> { + env_logger::init(); + + let args = Args::parse(); + let Args { + home_dir, + test_name, + } = args; + + match test_name.as_str() { + "test_success_move_to_another_account" => { + let res = pre_test(home_dir).await.unwrap(); + + let wrapped_node_core = res.5.clone(); + + info!("Waiting for first block creation"); + tokio::time::sleep(Duration::from_secs(TIME_TO_WAIT_FOR_BLOCK_SECONDS)).await; + + test_success_move_to_another_account(wrapped_node_core.clone()).await; + + post_test(res).await; + } + "test_success" => { + let res = pre_test(home_dir).await.unwrap(); + + let wrapped_node_core = res.5.clone(); + + info!("Waiting for first block creation"); + tokio::time::sleep(Duration::from_secs(TIME_TO_WAIT_FOR_BLOCK_SECONDS)).await; + + test_success(wrapped_node_core.clone()).await; + + post_test(res).await; + } + "test_failure" => { + let res = pre_test(home_dir).await.unwrap(); + + let wrapped_node_core = res.5.clone(); + + info!("Waiting for first block creation"); + tokio::time::sleep(Duration::from_secs(TIME_TO_WAIT_FOR_BLOCK_SECONDS)).await; + + test_failure(wrapped_node_core.clone()).await; + + post_test(res).await; + } + "all" => { + { + let res = pre_test(home_dir.clone()).await.unwrap(); + + let wrapped_node_core = res.5.clone(); + + info!("Waiting for first block creation"); + tokio::time::sleep(Duration::from_secs(TIME_TO_WAIT_FOR_BLOCK_SECONDS)).await; + + test_success_move_to_another_account(wrapped_node_core.clone()).await; + + post_test(res).await; + } + { + let res = pre_test(home_dir.clone()).await.unwrap(); + + let wrapped_node_core = res.5.clone(); + + info!("Waiting for first block creation"); + tokio::time::sleep(Duration::from_secs(TIME_TO_WAIT_FOR_BLOCK_SECONDS)).await; + + test_success(wrapped_node_core.clone()).await; + + post_test(res).await; + } + { + let res = pre_test(home_dir.clone()).await.unwrap(); + + let wrapped_node_core = res.5.clone(); + + info!("Waiting for first block creation"); + tokio::time::sleep(Duration::from_secs(TIME_TO_WAIT_FOR_BLOCK_SECONDS)).await; + + test_failure(wrapped_node_core.clone()).await; + + post_test(res).await; + } + } + _ => { + anyhow::bail!("Unknown test name"); + } + } + Ok(()) } diff --git a/sequencer_core/src/sequencer_store/accounts_store.rs b/sequencer_core/src/sequencer_store/accounts_store.rs index 8dd20700..9d5b7857 100644 --- a/sequencer_core/src/sequencer_store/accounts_store.rs +++ b/sequencer_core/src/sequencer_store/accounts_store.rs @@ -81,6 +81,10 @@ impl SequencerAccountsStore { } else { self.register_account(*account_addr); + let acc = self.accounts.get_mut(account_addr).unwrap(); + + acc.balance = new_balance; + 0 } } @@ -254,6 +258,6 @@ mod tests { assert_eq!(ret, 0); assert!(seq_acc_store.contains_account(&[1; 32])); - assert_eq!(seq_acc_store.get_account_balance(&[1; 32]), 0); + assert_eq!(seq_acc_store.get_account_balance(&[1; 32]), 100); } }