From a10671104b8a6449a2fba03ba0dfd6b5de5584a0 Mon Sep 17 00:00:00 2001 From: giladchase Date: Thu, 4 Jul 2024 18:01:43 +0300 Subject: [PATCH] fix: support parallel servers in tests (#357) In order to add additional integration tests, the Web and RPC servers must run on unique addresses, otherwise trying to create an additional server will fail due to the socket already being in use. This is achieved by selecting the port dynamically, through setting the port as 0 (dynamic port), which `local_addr` then resolves into an the actual port selected, that is, replacing `127.0.0.1:0` with `127.0.0.1:` Co-Authored-By: Gilad Chase --- .../src/integration_test_utils.rs | 18 +++++++++++++++++- crates/tests-integration/src/state_reader.rs | 7 ++++++- 2 files changed, 23 insertions(+), 2 deletions(-) diff --git a/crates/tests-integration/src/integration_test_utils.rs b/crates/tests-integration/src/integration_test_utils.rs index 08e6c370..b1a3995e 100644 --- a/crates/tests-integration/src/integration_test_utils.rs +++ b/crates/tests-integration/src/integration_test_utils.rs @@ -14,6 +14,7 @@ use starknet_gateway::gateway::Gateway; use starknet_gateway::rpc_state_reader::RpcStateReaderFactory; use starknet_mempool_types::communication::SharedMempoolClient; use test_utils::starknet_api_test_utils::external_tx_to_json; +use tokio::net::TcpListener; use crate::state_reader::spawn_test_rpc_state_reader; @@ -28,7 +29,7 @@ pub async fn create_gateway( ..Default::default() }; - let socket: SocketAddr = "127.0.0.1:3000".parse().unwrap(); + let socket = get_available_socket().await; let network_config = GatewayNetworkConfig { ip: socket.ip(), port: socket.port() }; let stateful_tx_validator_config = StatefulTransactionValidatorConfig::create_for_testing(); @@ -91,3 +92,18 @@ fn spawn_test_rpc_state_reader_config(rpc_server_addr: SocketAddr) -> RpcStateRe json_rpc_version: JSON_RPC_VERSION.to_string(), } } + +/// Returns a unique IP address and port for testing purposes. +/// +/// Tests run in parallel, so servers (like RPC or web) running on separate tests must have +/// different ports, otherwise the server will fail with "address already in use". +pub async fn get_available_socket() -> SocketAddr { + // Dinamically select port. + // First, set the port to 0 (dynamic port). + TcpListener::bind("127.0.0.1:0") + .await + .expect("Failed to bind to address") + // Then, resolve to the actual selected port. + .local_addr() + .expect("Failed to get local address") +} diff --git a/crates/tests-integration/src/state_reader.rs b/crates/tests-integration/src/state_reader.rs index d3a9f520..d16dc7ec 100644 --- a/crates/tests-integration/src/state_reader.rs +++ b/crates/tests-integration/src/state_reader.rs @@ -34,6 +34,8 @@ use tempfile::tempdir; use test_utils::starknet_api_test_utils::{deploy_account_tx, deployed_account_contract_address}; use tokio::sync::RwLock; +use crate::integration_test_utils::get_available_socket; + type ContractClassesMap = (Vec<(ClassHash, DeprecatedContractClass)>, Vec<(ClassHash, CasmContractClass)>); @@ -294,7 +296,10 @@ fn get_test_pending_classes() -> Arc> { } async fn run_papyrus_rpc_server(storage_reader: StorageReader) -> SocketAddr { - let rpc_config = RpcConfig::default(); + let rpc_config = RpcConfig { + server_address: get_available_socket().await.to_string(), + ..Default::default() + }; let (addr, handle) = run_server( &rpc_config, get_test_highest_block(),