diff --git a/crates/iota-cluster-test/src/cluster.rs b/crates/iota-cluster-test/src/cluster.rs index e493e73f4bc..1196961d9db 100644 --- a/crates/iota-cluster-test/src/cluster.rs +++ b/crates/iota-cluster-test/src/cluster.rs @@ -265,6 +265,7 @@ impl Cluster for LocalNewCluster { fullnode_url.clone(), ReaderWriterConfig::writer_mode(None), data_ingestion_path.clone(), + None, ) .await; @@ -274,6 +275,7 @@ impl Cluster for LocalNewCluster { fullnode_url.clone(), ReaderWriterConfig::reader_mode(indexer_address.to_string()), data_ingestion_path, + None, ) .await; } diff --git a/crates/iota-graphql-rpc/src/test_infra/cluster.rs b/crates/iota-graphql-rpc/src/test_infra/cluster.rs index 79d905cf1ff..36aff4343d1 100644 --- a/crates/iota-graphql-rpc/src/test_infra/cluster.rs +++ b/crates/iota-graphql-rpc/src/test_infra/cluster.rs @@ -73,6 +73,7 @@ pub async fn start_cluster( true, Some(data_ingestion_path), cancellation_token.clone(), + None, ) .await; @@ -137,6 +138,7 @@ pub async fn serve_executor( true, Some(data_ingestion_path), cancellation_token.clone(), + Some(&graphql_connection_config.db_name()), ) .await; diff --git a/crates/iota-indexer/README.md b/crates/iota-indexer/README.md index 1973532ee65..ce19b89f65d 100644 --- a/crates/iota-indexer/README.md +++ b/crates/iota-indexer/README.md @@ -104,7 +104,7 @@ The crate provides following tests currently: # run tests requiring only postgres integration cargo test --features pg_integration -- --test-threads 1 # run rpc tests with shared runtime -cargo test --features shared_test_runtime +cargo test --features shared_test_runtime -- --test-threads 1 ``` For a better testing experience is possible to use [nextest](https://nexte.st/) diff --git a/crates/iota-indexer/src/test_utils.rs b/crates/iota-indexer/src/test_utils.rs index fb00f19caba..4058acc5634 100644 --- a/crates/iota-indexer/src/test_utils.rs +++ b/crates/iota-indexer/src/test_utils.rs @@ -45,6 +45,7 @@ pub async fn start_test_indexer( rpc_url: String, reader_writer_config: ReaderWriterConfig, data_ingestion_path: PathBuf, + new_database: Option<&str>, ) -> (PgIndexerStore, JoinHandle>) { start_test_indexer_impl( db_url, @@ -54,6 +55,7 @@ pub async fn start_test_indexer( false, Some(data_ingestion_path), CancellationToken::new(), + new_database, ) .await } @@ -65,17 +67,23 @@ pub async fn start_test_indexer_impl( db_url: Option, rpc_url: String, reader_writer_config: ReaderWriterConfig, - reset_database: bool, + mut reset_database: bool, data_ingestion_path: Option, cancel: CancellationToken, + new_database: Option<&str>, ) -> (PgIndexerStore, JoinHandle>) { - let db_url = db_url.unwrap_or_else(|| { + let mut db_url = db_url.unwrap_or_else(|| { let pg_host = env::var("POSTGRES_HOST").unwrap_or_else(|_| "localhost".into()); let pg_port = env::var("POSTGRES_PORT").unwrap_or_else(|_| "32770".into()); let pw = env::var("POSTGRES_PASSWORD").unwrap_or_else(|_| "postgrespw".into()); format!("postgres://postgres:{pw}@{pg_host}:{pg_port}") }); + if let Some(new_database) = new_database { + db_url = replace_db_name(&db_url, new_database).0; + reset_database = true; + }; + let mut config = IndexerConfig { db_url: Some(db_url.clone().into()), rpc_client_url: rpc_url, diff --git a/crates/iota-indexer/tests/common/mod.rs b/crates/iota-indexer/tests/common/mod.rs index c6950a5e60c..58c5bb84513 100644 --- a/crates/iota-indexer/tests/common/mod.rs +++ b/crates/iota-indexer/tests/common/mod.rs @@ -9,7 +9,10 @@ use std::{ }; use diesel::PgConnection; -use iota_config::node::RunWithRange; +use iota_config::{ + local_ip_utils::{get_available_port, new_local_tcp_socket_for_testing}, + node::RunWithRange, +}; use iota_indexer::{ IndexerConfig, errors::IndexerError, @@ -33,7 +36,8 @@ use tempfile::tempdir; use test_cluster::{TestCluster, TestClusterBuilder}; use tokio::{runtime::Runtime, task::JoinHandle}; -const DEFAULT_DB_URL: &str = "postgres://postgres:postgrespw@localhost:5432/iota_indexer"; +const POSTGRES_URL: &str = "postgres://postgres:postgrespw@localhost:5432"; +const DEFAULT_DB: &str = "iota_indexer"; const DEFAULT_INDEXER_IP: &str = "127.0.0.1"; const DEFAULT_INDEXER_PORT: u16 = 9005; const DEFAULT_SERVER_PORT: u16 = 3000; @@ -53,8 +57,9 @@ impl ApiTestSetup { GLOBAL_API_TEST_SETUP.get_or_init(|| { let runtime = tokio::runtime::Runtime::new().unwrap(); - let (cluster, store, client) = - runtime.block_on(start_test_cluster_with_read_write_indexer(None)); + let (cluster, store, client) = runtime.block_on( + start_test_cluster_with_read_write_indexer(None, Some("shared_test_indexer_db")), + ); Self { runtime, @@ -66,10 +71,50 @@ impl ApiTestSetup { } } +pub struct SimulacrumTestSetup { + pub runtime: Runtime, + pub sim: Arc, + pub store: PgIndexerStore, + /// Indexer RPC Client + pub client: HttpClient, +} + +impl SimulacrumTestSetup { + pub fn get_or_init<'a>( + unique_env_name: &str, + env_initializer: impl Fn(PathBuf) -> Simulacrum, + initialized_env_container: &'a OnceLock, + ) -> &'a SimulacrumTestSetup { + initialized_env_container.get_or_init(|| { + let runtime = tokio::runtime::Runtime::new().unwrap(); + let data_ingestion_path = tempdir().unwrap().into_path(); + + let sim = env_initializer(data_ingestion_path.clone()); + let sim = Arc::new(sim); + + let db_name = format!("simulacrum_env_db_{}", unique_env_name); + let (_, store, _, client) = + runtime.block_on(start_simulacrum_rest_api_with_read_write_indexer( + sim.clone(), + data_ingestion_path, + Some(&db_name), + )); + + SimulacrumTestSetup { + runtime, + sim, + store, + client, + } + }) + } +} + /// Start a [`TestCluster`][`test_cluster::TestCluster`] with a `Read` & /// `Write` indexer pub async fn start_test_cluster_with_read_write_indexer( stop_cluster_after_checkpoint_seq: Option, + database_name: Option<&str>, ) -> (TestCluster, PgIndexerStore, HttpClient) { let temp = tempdir().unwrap().into_path(); let mut builder = TestClusterBuilder::new().with_data_ingestion_dir(temp.clone()); @@ -85,26 +130,32 @@ pub async fn start_test_cluster_with_read_write_indexer( // start indexer in write mode let (pg_store, _pg_store_handle) = start_test_indexer( - Some(DEFAULT_DB_URL.to_owned()), + Some(get_indexer_db_url(None)), cluster.rpc_url().to_string(), ReaderWriterConfig::writer_mode(None), temp.clone(), + database_name, ) .await; // start indexer in read mode - start_indexer_reader(cluster.rpc_url().to_owned(), temp); + let indexer_port = start_indexer_reader(cluster.rpc_url().to_owned(), temp, database_name); // create an RPC client by using the indexer url let rpc_client = HttpClientBuilder::default() - .build(format!( - "http://{DEFAULT_INDEXER_IP}:{DEFAULT_INDEXER_PORT}" - )) + .build(format!("http://{DEFAULT_INDEXER_IP}:{indexer_port}")) .unwrap(); (cluster, pg_store, rpc_client) } +fn get_indexer_db_url(database_name: Option<&str>) -> String { + database_name.map_or_else( + || format!("{POSTGRES_URL}/{DEFAULT_DB}"), + |db_name| format!("{POSTGRES_URL}/{db_name}"), + ) +} + /// Wait for the indexer to catch up to the given checkpoint sequence number /// /// Indexer starts storing data after checkpoint 0 @@ -192,14 +243,20 @@ pub async fn indexer_wait_for_transaction( } /// Start an Indexer instance in `Read` mode -fn start_indexer_reader(fullnode_rpc_url: impl Into, data_ingestion_path: PathBuf) { +fn start_indexer_reader( + fullnode_rpc_url: impl Into, + data_ingestion_path: PathBuf, + database_name: Option<&str>, +) -> u16 { + let db_url = get_indexer_db_url(database_name); + let port = get_available_port(DEFAULT_INDEXER_IP); let config = IndexerConfig { - db_url: Some(DEFAULT_DB_URL.to_owned().into()), + db_url: Some(db_url.clone().into()), rpc_client_url: fullnode_rpc_url.into(), reset_db: true, rpc_server_worker: true, rpc_server_url: DEFAULT_INDEXER_IP.to_owned(), - rpc_server_port: DEFAULT_INDEXER_PORT, + rpc_server_port: port, data_ingestion_path: Some(data_ingestion_path), ..Default::default() }; @@ -207,9 +264,10 @@ fn start_indexer_reader(fullnode_rpc_url: impl Into, data_ingestion_path let registry = prometheus::Registry::default(); init_metrics(®istry); - tokio::spawn(async move { - Indexer::start_reader::(&config, ®istry, DEFAULT_DB_URL.to_owned()).await - }); + tokio::spawn( + async move { Indexer::start_reader::(&config, ®istry, db_url).await }, + ); + port } /// Check if provided error message does match with @@ -228,24 +286,19 @@ pub fn rpc_call_error_msg_matches( }) } -pub fn get_default_fullnode_rpc_api_addr() -> SocketAddr { - format!("127.0.0.1:{}", DEFAULT_SERVER_PORT) - .parse() - .unwrap() -} - /// Set up a test indexer fetching from a REST endpoint served by the given /// Simulacrum. pub async fn start_simulacrum_rest_api_with_write_indexer( sim: Arc, data_ingestion_path: PathBuf, + server_url: Option, + database_name: Option<&str>, ) -> ( JoinHandle<()>, PgIndexerStore, JoinHandle>, ) { - let server_url = get_default_fullnode_rpc_api_addr(); - + let server_url = server_url.unwrap_or_else(new_local_tcp_socket_for_testing); let server_handle = tokio::spawn(async move { iota_rest_api::RestService::new_without_version(sim) .start_service(server_url) @@ -253,10 +306,11 @@ pub async fn start_simulacrum_rest_api_with_write_indexer( }); // Starts indexer let (pg_store, pg_handle) = start_test_indexer( - Some(DEFAULT_DB_URL.to_owned()), + Some(get_indexer_db_url(None)), format!("http://{}", server_url), ReaderWriterConfig::writer_mode(None), data_ingestion_path, + database_name, ) .await; (server_handle, pg_store, pg_handle) @@ -265,24 +319,32 @@ pub async fn start_simulacrum_rest_api_with_write_indexer( pub async fn start_simulacrum_rest_api_with_read_write_indexer( sim: Arc, data_ingestion_path: PathBuf, + database_name: Option<&str>, ) -> ( JoinHandle<()>, PgIndexerStore, JoinHandle>, HttpClient, ) { - let server_url = get_default_fullnode_rpc_api_addr(); - let (server_handle, pg_store, pg_handle) = - start_simulacrum_rest_api_with_write_indexer(sim, data_ingestion_path.clone()).await; + let simulacrum_server_url = new_local_tcp_socket_for_testing(); + let (server_handle, pg_store, pg_handle) = start_simulacrum_rest_api_with_write_indexer( + sim, + data_ingestion_path.clone(), + Some(simulacrum_server_url), + database_name, + ) + .await; // start indexer in read mode - start_indexer_reader(format!("http://{}", server_url), data_ingestion_path); + let indexer_port = start_indexer_reader( + format!("http://{}", simulacrum_server_url), + data_ingestion_path, + database_name, + ); // create an RPC client by using the indexer url let rpc_client = HttpClientBuilder::default() - .build(format!( - "http://{DEFAULT_INDEXER_IP}:{DEFAULT_INDEXER_PORT}" - )) + .build(format!("http://{DEFAULT_INDEXER_IP}:{indexer_port}")) .unwrap(); (server_handle, pg_store, pg_handle, rpc_client) diff --git a/crates/iota-indexer/tests/ingestion_tests.rs b/crates/iota-indexer/tests/ingestion_tests.rs index 0ed00313192..30f115c10f0 100644 --- a/crates/iota-indexer/tests/ingestion_tests.rs +++ b/crates/iota-indexer/tests/ingestion_tests.rs @@ -52,8 +52,13 @@ mod ingestion_tests { // Create a checkpoint which should include the transaction we executed. let checkpoint = sim.create_checkpoint(); - let (_, pg_store, _) = - start_simulacrum_rest_api_with_write_indexer(Arc::new(sim), data_ingestion_path).await; + let (_, pg_store, _) = start_simulacrum_rest_api_with_write_indexer( + Arc::new(sim), + data_ingestion_path, + None, + Some("indexer_ingestion_tests_db"), + ) + .await; indexer_wait_for_checkpoint(&pg_store, 1).await; @@ -97,8 +102,13 @@ mod ingestion_tests { // Create a checkpoint which should include the transaction we executed. let _ = sim.create_checkpoint(); - let (_, pg_store, _) = - start_simulacrum_rest_api_with_write_indexer(Arc::new(sim), data_ingestion_path).await; + let (_, pg_store, _) = start_simulacrum_rest_api_with_write_indexer( + Arc::new(sim), + data_ingestion_path, + None, + Some("indexer_ingestion_tests_db"), + ) + .await; indexer_wait_for_checkpoint(&pg_store, 1).await; diff --git a/crates/iota-indexer/tests/rpc-tests/extended_api.rs b/crates/iota-indexer/tests/rpc-tests/extended_api.rs index 82d5f4ff443..f77c156b3d4 100644 --- a/crates/iota-indexer/tests/rpc-tests/extended_api.rs +++ b/crates/iota-indexer/tests/rpc-tests/extended_api.rs @@ -1,7 +1,7 @@ // Copyright (c) 2024 IOTA Stiftung // SPDX-License-Identifier: Apache-2.0 -use std::{str::FromStr, sync::Arc}; +use std::{str::FromStr, sync::OnceLock}; use iota_json::{call_args, type_args}; use iota_json_rpc_api::{ @@ -18,431 +18,400 @@ use iota_types::{ quorum_driver_types::ExecuteTransactionRequestType, storage::ReadStore, }; -use serial_test::serial; use simulacrum::Simulacrum; use tempfile::tempdir; use test_cluster::TestCluster; -use crate::common::{ - indexer_wait_for_checkpoint, start_simulacrum_rest_api_with_read_write_indexer, - start_test_cluster_with_read_write_indexer, -}; - -#[tokio::test] -#[serial] -async fn get_epochs() { - let data_ingestion_path = tempdir().unwrap().into_path(); - let mut sim = Simulacrum::new(); - sim.set_data_ingestion_path(data_ingestion_path.clone()); - - execute_simulacrum_transactions(&mut sim, 15); - add_checkpoints(&mut sim, 300); - sim.advance_epoch(); - - execute_simulacrum_transactions(&mut sim, 10); - add_checkpoints(&mut sim, 300); - sim.advance_epoch(); - - execute_simulacrum_transactions(&mut sim, 5); - add_checkpoints(&mut sim, 300); +use crate::common::{ApiTestSetup, SimulacrumTestSetup, indexer_wait_for_checkpoint}; - let last_checkpoint = sim.get_latest_checkpoint().unwrap(); +static EXTENDED_API_SHARED_SIMULACRUM_INITIALIZED_ENV: OnceLock = + OnceLock::new(); - let (_, pg_store, _, indexer_client) = - start_simulacrum_rest_api_with_read_write_indexer(Arc::new(sim), data_ingestion_path).await; - indexer_wait_for_checkpoint(&pg_store, last_checkpoint.sequence_number).await; +fn get_or_init_shared_extended_api_simulacrum_env() -> &'static SimulacrumTestSetup { + SimulacrumTestSetup::get_or_init( + "extended_api", + |data_ingestion_path| { + let mut sim = Simulacrum::new(); + sim.set_data_ingestion_path(data_ingestion_path); - let epochs = indexer_client.get_epochs(None, None, None).await.unwrap(); + execute_simulacrum_transactions(&mut sim, 15); + add_checkpoints(&mut sim, 300); + sim.advance_epoch(); - assert_eq!(epochs.data.len(), 3); - assert!(!epochs.has_next_page); + execute_simulacrum_transactions(&mut sim, 10); + add_checkpoints(&mut sim, 300); + sim.advance_epoch(); - let end_of_epoch_info = epochs.data[0].end_of_epoch_info.as_ref().unwrap(); - assert_eq!(epochs.data[0].epoch, 0); - assert_eq!(epochs.data[0].first_checkpoint_id, 0); - assert_eq!(epochs.data[0].epoch_total_transactions, 17); - assert_eq!(end_of_epoch_info.last_checkpoint_id, 301); + execute_simulacrum_transactions(&mut sim, 5); + add_checkpoints(&mut sim, 300); - let end_of_epoch_info = epochs.data[1].end_of_epoch_info.as_ref().unwrap(); - assert_eq!(epochs.data[1].epoch, 1); - assert_eq!(epochs.data[1].first_checkpoint_id, 302); - assert_eq!(epochs.data[1].epoch_total_transactions, 11); - assert_eq!(end_of_epoch_info.last_checkpoint_id, 602); - - assert_eq!(epochs.data[2].epoch, 2); - assert_eq!(epochs.data[2].first_checkpoint_id, 603); - assert_eq!(epochs.data[2].epoch_total_transactions, 0); - assert!(epochs.data[2].end_of_epoch_info.is_none()); + sim + }, + &EXTENDED_API_SHARED_SIMULACRUM_INITIALIZED_ENV, + ) } -#[tokio::test] -#[serial] -async fn get_epochs_descending() { - let data_ingestion_path = tempdir().unwrap().into_path(); - let mut sim = Simulacrum::new(); - sim.set_data_ingestion_path(data_ingestion_path.clone()); - - execute_simulacrum_transactions(&mut sim, 15); - add_checkpoints(&mut sim, 300); - sim.advance_epoch(); - - execute_simulacrum_transactions(&mut sim, 10); - add_checkpoints(&mut sim, 300); - sim.advance_epoch(); - - execute_simulacrum_transactions(&mut sim, 5); - add_checkpoints(&mut sim, 300); - - let last_checkpoint = sim.get_latest_checkpoint().unwrap(); - - let (_, pg_store, _, indexer_client) = - start_simulacrum_rest_api_with_read_write_indexer(Arc::new(sim), data_ingestion_path).await; - indexer_wait_for_checkpoint(&pg_store, last_checkpoint.sequence_number).await; - - let epochs = indexer_client - .get_epochs(None, None, Some(true)) - .await - .unwrap(); - - let actual_epochs_order = epochs - .data - .iter() - .map(|epoch| epoch.epoch) - .collect::>(); - - assert_eq!(epochs.data.len(), 3); - assert!(!epochs.has_next_page); - assert_eq!(actual_epochs_order, [2, 1, 0]) +#[test] +fn get_epochs() { + let SimulacrumTestSetup { + runtime, + sim, + store, + client, + } = get_or_init_shared_extended_api_simulacrum_env(); + + runtime.block_on(async move { + let last_checkpoint = sim.get_latest_checkpoint().unwrap(); + indexer_wait_for_checkpoint(&store, last_checkpoint.sequence_number).await; + + let epochs = client.get_epochs(None, None, None).await.unwrap(); + + assert_eq!(epochs.data.len(), 3); + assert!(!epochs.has_next_page); + + let end_of_epoch_info = epochs.data[0].end_of_epoch_info.as_ref().unwrap(); + assert_eq!(epochs.data[0].epoch, 0); + assert_eq!(epochs.data[0].first_checkpoint_id, 0); + assert_eq!(epochs.data[0].epoch_total_transactions, 17); + assert_eq!(end_of_epoch_info.last_checkpoint_id, 301); + + let end_of_epoch_info = epochs.data[1].end_of_epoch_info.as_ref().unwrap(); + assert_eq!(epochs.data[1].epoch, 1); + assert_eq!(epochs.data[1].first_checkpoint_id, 302); + assert_eq!(epochs.data[1].epoch_total_transactions, 11); + assert_eq!(end_of_epoch_info.last_checkpoint_id, 602); + + assert_eq!(epochs.data[2].epoch, 2); + assert_eq!(epochs.data[2].first_checkpoint_id, 603); + assert_eq!(epochs.data[2].epoch_total_transactions, 0); + assert!(epochs.data[2].end_of_epoch_info.is_none()); + }); } -#[tokio::test] -#[serial] -async fn get_epochs_paging() { - let data_ingestion_path = tempdir().unwrap().into_path(); - let mut sim = Simulacrum::new(); - sim.set_data_ingestion_path(data_ingestion_path.clone()); - - execute_simulacrum_transactions(&mut sim, 15); - add_checkpoints(&mut sim, 300); - sim.advance_epoch(); - - execute_simulacrum_transactions(&mut sim, 10); - add_checkpoints(&mut sim, 300); - sim.advance_epoch(); - - execute_simulacrum_transactions(&mut sim, 5); - add_checkpoints(&mut sim, 300); - - let last_checkpoint = sim.get_latest_checkpoint().unwrap(); - - let (_, pg_store, _, indexer_client) = - start_simulacrum_rest_api_with_read_write_indexer(Arc::new(sim), data_ingestion_path).await; - indexer_wait_for_checkpoint(&pg_store, last_checkpoint.sequence_number).await; - - let epochs = indexer_client - .get_epochs(None, Some(2), None) - .await - .unwrap(); - let actual_epochs_order = epochs - .data - .iter() - .map(|epoch| epoch.epoch) - .collect::>(); - - assert_eq!(epochs.data.len(), 2); - assert!(epochs.has_next_page); - assert_eq!(epochs.next_cursor, Some(1.into())); - assert_eq!(actual_epochs_order, [0, 1]); - - let epochs = indexer_client - .get_epochs(Some(1.into()), Some(2), None) - .await - .unwrap(); - let actual_epochs_order = epochs - .data - .iter() - .map(|epoch| epoch.epoch) - .collect::>(); - - assert_eq!(epochs.data.len(), 1); - assert!(!epochs.has_next_page); - assert_eq!(epochs.next_cursor, Some(2.into())); - assert_eq!(actual_epochs_order, [2]); +#[test] +fn get_epochs_descending() { + let SimulacrumTestSetup { + runtime, + sim, + store, + client, + } = get_or_init_shared_extended_api_simulacrum_env(); + + runtime.block_on(async move { + let last_checkpoint = sim.get_latest_checkpoint().unwrap(); + indexer_wait_for_checkpoint(&store, last_checkpoint.sequence_number).await; + + let epochs = client.get_epochs(None, None, Some(true)).await.unwrap(); + + let actual_epochs_order = epochs + .data + .iter() + .map(|epoch| epoch.epoch) + .collect::>(); + + assert_eq!(epochs.data.len(), 3); + assert!(!epochs.has_next_page); + assert_eq!(actual_epochs_order, [2, 1, 0]) + }); } -#[tokio::test] -#[serial] -async fn get_epoch_metrics() { - let data_ingestion_path = tempdir().unwrap().into_path(); - let mut sim = Simulacrum::new(); - sim.set_data_ingestion_path(data_ingestion_path.clone()); - - execute_simulacrum_transactions(&mut sim, 15); - add_checkpoints(&mut sim, 300); - sim.advance_epoch(); - - execute_simulacrum_transactions(&mut sim, 10); - add_checkpoints(&mut sim, 300); - sim.advance_epoch(); - - execute_simulacrum_transactions(&mut sim, 5); - add_checkpoints(&mut sim, 300); - - let last_checkpoint = sim.get_latest_checkpoint().unwrap(); - - let (_, pg_store, _, indexer_client) = - start_simulacrum_rest_api_with_read_write_indexer(Arc::new(sim), data_ingestion_path).await; - indexer_wait_for_checkpoint(&pg_store, last_checkpoint.sequence_number).await; - - let epoch_metrics = indexer_client - .get_epoch_metrics(None, None, None) - .await - .unwrap(); - - assert_eq!(epoch_metrics.data.len(), 3); - assert!(!epoch_metrics.has_next_page); - - let end_of_epoch_info = epoch_metrics.data[0].end_of_epoch_info.as_ref().unwrap(); - assert_eq!(epoch_metrics.data[0].epoch, 0); - assert_eq!(epoch_metrics.data[0].first_checkpoint_id, 0); - assert_eq!(epoch_metrics.data[0].epoch_total_transactions, 17); - assert_eq!(end_of_epoch_info.last_checkpoint_id, 301); - - let end_of_epoch_info = epoch_metrics.data[1].end_of_epoch_info.as_ref().unwrap(); - assert_eq!(epoch_metrics.data[1].epoch, 1); - assert_eq!(epoch_metrics.data[1].first_checkpoint_id, 302); - assert_eq!(epoch_metrics.data[1].epoch_total_transactions, 11); - assert_eq!(end_of_epoch_info.last_checkpoint_id, 602); - - assert_eq!(epoch_metrics.data[2].epoch, 2); - assert_eq!(epoch_metrics.data[2].first_checkpoint_id, 603); - assert_eq!(epoch_metrics.data[2].epoch_total_transactions, 0); - assert!(epoch_metrics.data[2].end_of_epoch_info.is_none()); +#[test] +fn get_epochs_paging() { + let SimulacrumTestSetup { + runtime, + sim, + store, + client, + } = get_or_init_shared_extended_api_simulacrum_env(); + + runtime.block_on(async move { + let last_checkpoint = sim.get_latest_checkpoint().unwrap(); + indexer_wait_for_checkpoint(&store, last_checkpoint.sequence_number).await; + + let epochs = client.get_epochs(None, Some(2), None).await.unwrap(); + let actual_epochs_order = epochs + .data + .iter() + .map(|epoch| epoch.epoch) + .collect::>(); + + assert_eq!(epochs.data.len(), 2); + assert!(epochs.has_next_page); + assert_eq!(epochs.next_cursor, Some(1.into())); + assert_eq!(actual_epochs_order, [0, 1]); + + let epochs = client + .get_epochs(Some(1.into()), Some(2), None) + .await + .unwrap(); + let actual_epochs_order = epochs + .data + .iter() + .map(|epoch| epoch.epoch) + .collect::>(); + + assert_eq!(epochs.data.len(), 1); + assert!(!epochs.has_next_page); + assert_eq!(epochs.next_cursor, Some(2.into())); + assert_eq!(actual_epochs_order, [2]); + }); } -#[tokio::test] -#[serial] -async fn get_epoch_metrics_descending() { - let data_ingestion_path = tempdir().unwrap().into_path(); - let mut sim = Simulacrum::new(); - sim.set_data_ingestion_path(data_ingestion_path.clone()); - - execute_simulacrum_transactions(&mut sim, 15); - add_checkpoints(&mut sim, 300); - sim.advance_epoch(); - - execute_simulacrum_transactions(&mut sim, 10); - add_checkpoints(&mut sim, 300); - sim.advance_epoch(); - - execute_simulacrum_transactions(&mut sim, 5); - add_checkpoints(&mut sim, 300); - - let last_checkpoint = sim.get_latest_checkpoint().unwrap(); - - let (_, pg_store, _, indexer_client) = - start_simulacrum_rest_api_with_read_write_indexer(Arc::new(sim), data_ingestion_path).await; - indexer_wait_for_checkpoint(&pg_store, last_checkpoint.sequence_number).await; - - let epochs = indexer_client - .get_epoch_metrics(None, None, Some(true)) - .await - .unwrap(); - - let actual_epochs_order = epochs - .data - .iter() - .map(|epoch| epoch.epoch) - .collect::>(); - - assert_eq!(epochs.data.len(), 3); - assert!(!epochs.has_next_page); - assert_eq!(actual_epochs_order, [2, 1, 0]) +#[test] +fn get_epoch_metrics() { + let SimulacrumTestSetup { + runtime, + sim, + store, + client, + } = get_or_init_shared_extended_api_simulacrum_env(); + + runtime.block_on(async move { + let last_checkpoint = sim.get_latest_checkpoint().unwrap(); + indexer_wait_for_checkpoint(&store, last_checkpoint.sequence_number).await; + + let epoch_metrics = client.get_epoch_metrics(None, None, None).await.unwrap(); + + assert_eq!(epoch_metrics.data.len(), 3); + assert!(!epoch_metrics.has_next_page); + + let end_of_epoch_info = epoch_metrics.data[0].end_of_epoch_info.as_ref().unwrap(); + assert_eq!(epoch_metrics.data[0].epoch, 0); + assert_eq!(epoch_metrics.data[0].first_checkpoint_id, 0); + assert_eq!(epoch_metrics.data[0].epoch_total_transactions, 17); + assert_eq!(end_of_epoch_info.last_checkpoint_id, 301); + + let end_of_epoch_info = epoch_metrics.data[1].end_of_epoch_info.as_ref().unwrap(); + assert_eq!(epoch_metrics.data[1].epoch, 1); + assert_eq!(epoch_metrics.data[1].first_checkpoint_id, 302); + assert_eq!(epoch_metrics.data[1].epoch_total_transactions, 11); + assert_eq!(end_of_epoch_info.last_checkpoint_id, 602); + + assert_eq!(epoch_metrics.data[2].epoch, 2); + assert_eq!(epoch_metrics.data[2].first_checkpoint_id, 603); + assert_eq!(epoch_metrics.data[2].epoch_total_transactions, 0); + assert!(epoch_metrics.data[2].end_of_epoch_info.is_none()); + }); } -#[tokio::test] -#[serial] -async fn get_epoch_metrics_paging() { - let data_ingestion_path = tempdir().unwrap().into_path(); - let mut sim = Simulacrum::new(); - sim.set_data_ingestion_path(data_ingestion_path.clone()); - - execute_simulacrum_transactions(&mut sim, 15); - add_checkpoints(&mut sim, 300); - sim.advance_epoch(); - - execute_simulacrum_transactions(&mut sim, 10); - add_checkpoints(&mut sim, 300); - sim.advance_epoch(); - - execute_simulacrum_transactions(&mut sim, 5); - add_checkpoints(&mut sim, 300); - - let last_checkpoint = sim.get_latest_checkpoint().unwrap(); - - let (_, pg_store, _, indexer_client) = - start_simulacrum_rest_api_with_read_write_indexer(Arc::new(sim), data_ingestion_path).await; - indexer_wait_for_checkpoint(&pg_store, last_checkpoint.sequence_number).await; - - let epochs = indexer_client - .get_epoch_metrics(None, Some(2), None) - .await - .unwrap(); - let actual_epochs_order = epochs - .data - .iter() - .map(|epoch| epoch.epoch) - .collect::>(); - - assert_eq!(epochs.data.len(), 2); - assert!(epochs.has_next_page); - assert_eq!(epochs.next_cursor, Some(1.into())); - assert_eq!(actual_epochs_order, [0, 1]); - - let epochs = indexer_client - .get_epoch_metrics(Some(1.into()), Some(2), None) - .await - .unwrap(); - let actual_epochs_order = epochs - .data - .iter() - .map(|epoch| epoch.epoch) - .collect::>(); - - assert_eq!(epochs.data.len(), 1); - assert!(!epochs.has_next_page); - assert_eq!(epochs.next_cursor, Some(2.into())); - assert_eq!(actual_epochs_order, [2]); +#[test] +fn get_epoch_metrics_descending() { + let SimulacrumTestSetup { + runtime, + sim, + store, + client, + } = get_or_init_shared_extended_api_simulacrum_env(); + + runtime.block_on(async move { + let last_checkpoint = sim.get_latest_checkpoint().unwrap(); + indexer_wait_for_checkpoint(&store, last_checkpoint.sequence_number).await; + + let epochs = client + .get_epoch_metrics(None, None, Some(true)) + .await + .unwrap(); + + let actual_epochs_order = epochs + .data + .iter() + .map(|epoch| epoch.epoch) + .collect::>(); + + assert_eq!(epochs.data.len(), 3); + assert!(!epochs.has_next_page); + assert_eq!(actual_epochs_order, [2, 1, 0]); + }); } -#[tokio::test] -#[serial] -async fn get_current_epoch() { - let data_ingestion_path = tempdir().unwrap().into_path(); - let mut sim = Simulacrum::new(); - sim.set_data_ingestion_path(data_ingestion_path.clone()); - - execute_simulacrum_transactions(&mut sim, 15); - add_checkpoints(&mut sim, 300); - sim.advance_epoch(); - - execute_simulacrum_transactions(&mut sim, 10); - add_checkpoints(&mut sim, 300); - sim.advance_epoch(); - - execute_simulacrum_transactions(&mut sim, 5); - add_checkpoints(&mut sim, 300); - - let last_checkpoint = sim.get_latest_checkpoint().unwrap(); - - let (_, pg_store, _, indexer_client) = - start_simulacrum_rest_api_with_read_write_indexer(Arc::new(sim), data_ingestion_path).await; - indexer_wait_for_checkpoint(&pg_store, last_checkpoint.sequence_number).await; - - let current_epoch = indexer_client.get_current_epoch().await.unwrap(); +#[test] +fn get_epoch_metrics_paging() { + let SimulacrumTestSetup { + runtime, + sim, + store, + client, + } = get_or_init_shared_extended_api_simulacrum_env(); + + runtime.block_on(async move { + let last_checkpoint = sim.get_latest_checkpoint().unwrap(); + indexer_wait_for_checkpoint(&store, last_checkpoint.sequence_number).await; + + let epochs = client.get_epoch_metrics(None, Some(2), None).await.unwrap(); + let actual_epochs_order = epochs + .data + .iter() + .map(|epoch| epoch.epoch) + .collect::>(); + + assert_eq!(epochs.data.len(), 2); + assert!(epochs.has_next_page); + assert_eq!(epochs.next_cursor, Some(1.into())); + assert_eq!(actual_epochs_order, [0, 1]); + + let epochs = client + .get_epoch_metrics(Some(1.into()), Some(2), None) + .await + .unwrap(); + let actual_epochs_order = epochs + .data + .iter() + .map(|epoch| epoch.epoch) + .collect::>(); + + assert_eq!(epochs.data.len(), 1); + assert!(!epochs.has_next_page); + assert_eq!(epochs.next_cursor, Some(2.into())); + assert_eq!(actual_epochs_order, [2]); + }); +} - assert_eq!(current_epoch.epoch, 2); - assert_eq!(current_epoch.first_checkpoint_id, 603); - assert_eq!(current_epoch.epoch_total_transactions, 0); - assert!(current_epoch.end_of_epoch_info.is_none()); +#[test] +fn get_current_epoch() { + let SimulacrumTestSetup { + runtime, + sim, + store, + client, + } = get_or_init_shared_extended_api_simulacrum_env(); + + runtime.block_on(async move { + let last_checkpoint = sim.get_latest_checkpoint().unwrap(); + indexer_wait_for_checkpoint(&store, last_checkpoint.sequence_number).await; + + let current_epoch = client.get_current_epoch().await.unwrap(); + + assert_eq!(current_epoch.epoch, 2); + assert_eq!(current_epoch.first_checkpoint_id, 603); + assert_eq!(current_epoch.epoch_total_transactions, 0); + assert!(current_epoch.end_of_epoch_info.is_none()); + }); } #[ignore = "https://github.com/iotaledger/iota/issues/2197#issuecomment-2371642744"] -#[tokio::test] -#[serial] -async fn get_network_metrics() { - let (_, pg_store, indexer_client) = start_test_cluster_with_read_write_indexer(None).await; - indexer_wait_for_checkpoint(&pg_store, 10).await; - - let network_metrics = indexer_client.get_network_metrics().await.unwrap(); - - println!("{:#?}", network_metrics); +#[test] +fn get_network_metrics() { + let ApiTestSetup { + runtime, + store, + client, + .. + } = ApiTestSetup::get_or_init(); + + runtime.block_on(async move { + indexer_wait_for_checkpoint(&store, 10).await; + + let network_metrics = client.get_network_metrics().await.unwrap(); + + println!("{:#?}", network_metrics); + }); } #[ignore = "https://github.com/iotaledger/iota/issues/2197#issuecomment-2371642744"] -#[tokio::test] -#[serial] -async fn get_move_call_metrics() { - let (cluster, pg_store, indexer_client) = - start_test_cluster_with_read_write_indexer(None).await; - - execute_move_fn(&cluster).await.unwrap(); - - let latest_checkpoint_sn = cluster - .rpc_client() - .get_latest_checkpoint_sequence_number() - .await - .unwrap(); - indexer_wait_for_checkpoint(&pg_store, latest_checkpoint_sn.into_inner()).await; - - let move_call_metrics = indexer_client.get_move_call_metrics().await.unwrap(); - - // TODO: Why is the move call not included in the stats? - assert_eq!(move_call_metrics.rank_3_days.len(), 0); - assert_eq!(move_call_metrics.rank_7_days.len(), 0); - assert_eq!(move_call_metrics.rank_30_days.len(), 0); +#[test] +fn get_move_call_metrics() { + let ApiTestSetup { + runtime, + store, + client, + cluster, + .. + } = ApiTestSetup::get_or_init(); + + runtime.block_on(async move { + execute_move_fn(&cluster).await.unwrap(); + + let latest_checkpoint_sn = cluster + .rpc_client() + .get_latest_checkpoint_sequence_number() + .await + .unwrap(); + indexer_wait_for_checkpoint(&store, latest_checkpoint_sn.into_inner()).await; + + let move_call_metrics = client.get_move_call_metrics().await.unwrap(); + + // TODO: Why is the move call not included in the stats? + assert_eq!(move_call_metrics.rank_3_days.len(), 0); + assert_eq!(move_call_metrics.rank_7_days.len(), 0); + assert_eq!(move_call_metrics.rank_30_days.len(), 0); + }); } #[ignore = "https://github.com/iotaledger/iota/issues/2197#issuecomment-2371642744"] -#[tokio::test] -#[serial] -async fn get_latest_address_metrics() { - let (_, pg_store, indexer_client) = start_test_cluster_with_read_write_indexer(None).await; - indexer_wait_for_checkpoint(&pg_store, 10).await; - - let address_metrics = indexer_client.get_latest_address_metrics().await.unwrap(); - - println!("{:#?}", address_metrics); +#[test] +fn get_latest_address_metrics() { + let ApiTestSetup { + runtime, + store, + client, + .. + } = ApiTestSetup::get_or_init(); + + runtime.block_on(async move { + indexer_wait_for_checkpoint(&store, 10).await; + + let address_metrics = client.get_latest_address_metrics().await.unwrap(); + + println!("{:#?}", address_metrics); + }); } #[ignore = "https://github.com/iotaledger/iota/issues/2197#issuecomment-2371642744"] -#[tokio::test] -#[serial] -async fn get_checkpoint_address_metrics() { - let (_, pg_store, indexer_client) = start_test_cluster_with_read_write_indexer(None).await; - indexer_wait_for_checkpoint(&pg_store, 10).await; - - let address_metrics = indexer_client - .get_checkpoint_address_metrics(0) - .await - .unwrap(); - - println!("{:#?}", address_metrics); +#[test] +fn get_checkpoint_address_metrics() { + let ApiTestSetup { + runtime, + store, + client, + .. + } = ApiTestSetup::get_or_init(); + + runtime.block_on(async move { + indexer_wait_for_checkpoint(&store, 10).await; + + let address_metrics = client.get_checkpoint_address_metrics(0).await.unwrap(); + + println!("{:#?}", address_metrics); + }); } #[ignore = "https://github.com/iotaledger/iota/issues/2197#issuecomment-2371642744"] -#[tokio::test] -#[serial] -async fn get_all_epoch_address_metrics() { - let (_, pg_store, indexer_client) = start_test_cluster_with_read_write_indexer(None).await; - indexer_wait_for_checkpoint(&pg_store, 10).await; - - let address_metrics = indexer_client - .get_all_epoch_address_metrics(None) - .await - .unwrap(); - - println!("{:#?}", address_metrics); +#[test] +fn get_all_epoch_address_metrics() { + let ApiTestSetup { + runtime, + store, + client, + .. + } = ApiTestSetup::get_or_init(); + + runtime.block_on(async move { + indexer_wait_for_checkpoint(&store, 10).await; + + let address_metrics = client.get_all_epoch_address_metrics(None).await.unwrap(); + + println!("{:#?}", address_metrics); + }); } -#[tokio::test] -#[serial] -async fn get_total_transactions() { - let data_ingestion_path = tempdir().unwrap().into_path(); - let mut sim = Simulacrum::new(); - sim.set_data_ingestion_path(data_ingestion_path.clone()); - execute_simulacrum_transactions(&mut sim, 5); - - let latest_checkpoint = sim.create_checkpoint(); - let total_transactions_count = latest_checkpoint.network_total_transactions; - - let (_, pg_store, _, indexer_client) = - start_simulacrum_rest_api_with_read_write_indexer(Arc::new(sim), data_ingestion_path).await; - indexer_wait_for_checkpoint(&pg_store, latest_checkpoint.sequence_number).await; - - let transactions_cnt = indexer_client.get_total_transactions().await.unwrap(); - assert_eq!(transactions_cnt.into_inner(), total_transactions_count); - assert_eq!(transactions_cnt.into_inner(), 6); +#[test] +fn get_total_transactions() { + let SimulacrumTestSetup { + runtime, + sim, + store, + client, + } = get_or_init_shared_extended_api_simulacrum_env(); + + runtime.block_on(async move { + let latest_checkpoint = sim.get_latest_checkpoint().unwrap(); + let total_transactions_count = latest_checkpoint.network_total_transactions; + indexer_wait_for_checkpoint(&store, latest_checkpoint.sequence_number).await; + + let transactions_cnt = client.get_total_transactions().await.unwrap(); + assert_eq!(transactions_cnt.into_inner(), total_transactions_count); + assert_eq!(transactions_cnt.into_inner(), 33); + }); } async fn execute_move_fn(cluster: &TestCluster) -> Result<(), anyhow::Error> { diff --git a/crates/iota-indexer/tests/rpc-tests/main.rs b/crates/iota-indexer/tests/rpc-tests/main.rs index 5c7dd6490c7..bd1a3788c89 100644 --- a/crates/iota-indexer/tests/rpc-tests/main.rs +++ b/crates/iota-indexer/tests/rpc-tests/main.rs @@ -4,7 +4,7 @@ #[allow(dead_code)] #[path = "../common/mod.rs"] mod common; -#[cfg(feature = "pg_integration")] +#[cfg(feature = "shared_test_runtime")] mod extended_api; #[cfg(feature = "shared_test_runtime")] mod governance_api;